class IUP_MATRIX
-- Creates a matrix of alphanumeric fields. Therefore, all values of the matrix 
-- fields are strings. The matrix is not a grid container like many systems 
-- have. It inherits from IUP_CANVAS.
--
-- This is an additional control that depends on the CD library. You should 
-- call "load_controls" to use it.
--
-- It has two modes of operation: normal and callback mode. In normal mode, 
-- string values are stored in attributes for each cell. In callback mode these 
-- attributes are ignored and the cells are filled with strings returned by the 
-- "VALUE_CB" callback. So the existence of this callback defines the mode the 
-- matrix will operate.
--
-- Notice that it is possible to use the IUP_FLAT_SCROLL_BOX to overcome the 
-- internal scrollbars of another control like IUP_MATRIX by making all cells 
-- visible, but this will force all cells to be drawn all the time even when 
-- not visible at the scroll box, which is much slower than the internal 
-- IUP_MATRIX optimization. So, by default, this is not used.

inherit
	IUP_CONTROLS
		rename
			canvas as matrix
		redefine
			matrix,
			set_cursor,
			set_border,
			set_scroll_bar,
			execute_action_fniiiis,
			execute_click_fniis,
			execute_colresize,
			execute_release,
			execute_resizematrix,
			execute_togglevalue_fniii,
			execute_valuechanged,
			execute_mousemove,
			execute_enteritem,
			execute_leaveitem,
			execute_scrolltop,
			execute_bgcolor,
			execute_fgcolor,
			execute_font,
			execute_type,
			execute_draw,
			execute_dropcheck,
			execute_translatevalue,
			execute_drop,
			execute_menudrop,
			execute_dropselect,
			execute_edition,
			execute_value,
			execute_value_edit,
			execute_mark,
			execute_markedit
		end
	IUP_WIDGET_FGCOLOR
	IUP_WIDGET_FLAT_SCROLL_BOX
	IUP_WIDGET_TEXT_POS

create {ANY}
   matrix

feature {ANY}

	matrix
		local
			p, a_matrix: POINTER
		do
			a_matrix := int_matrix (p)

			set_widget(a_matrix)
			
			create_mask_dictionary
		end

	-- General Attributes

	set_cursor (name: STRING)
		-- Default cursor used by the matrix. The default cursor is a symbol that 
		-- looks like a cross. If you need to refer to this default cursor, use 
		-- the name "IupMatrixCrossCursor".
		do
			Precursor (name)
		end

	set_drop_image (name: STRING)
		-- drop image name. Use set_attribute_handle to associate an image to a 
		-- name. See also IUP_IMAGE. By default an internal image will be used.
		do
			iup_open.set_attribute(Current, "DROPIMAGE", name)
		end

	set_focus_cell (line, column: INTEGER)
		-- Defines the current cell (line>0 and column>0, a title cell can NOT be 
		-- the current cell). Default: "1:1".
		require
			non_negative: line >= 0
							  column >= 0
		local
			str: STRING
		do
			str := line.to_string
			str.append_string(":")
			str.append_string(column.to_string)

			iup_open.set_attribute(Current, "FOCUSCELL", str)
		end

	get_focus_cell: TUPLE[INTEGER, INTEGER]
		-- Returns the [line, column] of the focus cell.
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "FOCUSCELL")
			
			Result := components_of (str, ':')
		end

	set_flat (state: BOOLEAN)
		-- Removes the 3D appearance from the matrix.
		do
			iup_open.set_attribute(Current, "FLAT", boolean_to_yesno(state))
		end

	set_hide_focus (state: BOOLEAN)
		-- Do not show the focus mark when drawing the matrix. Default is False.
		do
			iup_open.set_attribute(Current, "HIDEFOCUS", boolean_to_yesno(state))
		end

	set_hidden_text_marks (state: BOOLEAN)
		-- When text is greater than cell space, it is normally cropped, but when 
		-- set to "True" a "..." mark will be added at the crop point to indicate 
		-- that there is more text not visible. Default: "False".
		do
			iup_open.set_attribute(Current, "HIDDENTEXTMARKS", boolean_to_yesno(state))
		end

	set_highlight_color (red, green, blue: INTEGER)
		-- (non inheritable): the overlay color for the selected cells. 
		-- Default: TXTHLCOLOR global attribute. The color is composited using 
		-- "set_highlight_color_alpha" attribute.
		do
			iup_open.set_attribute(Current, "HLCOLOR", rgb_to_string(red, green, blue))
		end

	set_highlight_color_alpha (alpha: INTEGER)
		-- Alpha value to be used for selected cell (default is 128).
		require
         alpha >= 0
         alpha <= 255
		do
			iup_open.set_attribute(Current, "HLCOLORALPHA", alpha.to_string)
		end

	set_origin (line, column: INTEGER)
		-- Scroll the visible area to the given cell. 
		require
			line > 0
			column > 0
		local
			str: STRING
		do
			str := line.to_string
			str.append_string(":")
			str.append_string(column.to_string)

			iup_open.set_attribute(Current, "ORIGIN", str)
		end

	get_origin: TUPLE[INTEGER, INTEGER]
		-- Returns the cell at the upper left corner.
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "ORIGIN")
			
			Result := components_of (str, ':')
		end

	set_line (line: INTEGER)
		-- Scroll to a specific line.
		require
			line > 0
		local
			str: STRING
		do
			str := line.to_string
			str.append_string(":")
			str.append_string("*")

			iup_open.set_attribute(Current, "ORIGIN", str)
		end

	set_column (column: INTEGER)
		-- Scroll to a specific column.
		require
			column > 0
		local
			str: STRING
		do
			str := "*:"
			str.append_string(column.to_string)

			iup_open.set_attribute(Current, "ORIGIN", str)
		end

	set_origin_offset (x, y: INTEGER)
		-- Complements the ORIGIN attribute by specifying the drag offset of the 
		-- top left cell. When changing this attribute must change also ORIGIN 
		-- right after.
		require
			non_negative: x >= 0
							  y >= 0
		local
			str: STRING
		do
			str := x.to_string
			str.append_string(":")
			str.append_string(y.to_string)

			iup_open.set_attribute(Current, "ORIGINOFFSET", str)
		end

	set_read_only (state: BOOLEAN)
		-- Disables the editing of all cells. The callback "edition" 
		-- and "value_edit" will not be called anymore. The features to change 
		-- the cell value still work.
		do
			iup_open.set_attribute(Current, "READONLY", boolean_to_yesno(state))
		end

	set_show_fill_value (state: BOOLEAN)
		-- Enable the display of the numeric percentage in the cell when type is 
		-- "FILL". Default: False.
		do
			iup_open.set_attribute(Current, "SHOWFILLVALUE", boolean_to_yesno(state))
		end

	set_toggle_centered (state: BOOLEAN)
		-- Center the toggle. No text will be drawn.
		do
			iup_open.set_attribute(Current, "TOGGLECENTERED", boolean_to_yesno(state))
		end

	set_toggle_image_on (name: STRING)
		-- Toggle image name when state is ON. See also IUP_IMAGE. By default an 
		-- internal image will be used.
		do
			iup_open.set_attribute(Current, "TOGGLEIMAGEON", name)
		end

	set_toggle_image_off (name: STRING)
		-- Toggle image name when state is OFF. See also IUP_IMAGE. By default an 
		-- internal image will be used.
		do
			iup_open.set_attribute(Current, "TOGGLEIMAGEOFF", name)
		end

	set_type_color_inactive (state: BOOLEAN)
		-- When inactive the color of the cell of type "COLOR" will be 
		-- attenuated as everything else. Default: True.
		do
			iup_open.set_attribute(Current, "TYPECOLORINACTIVE", boolean_to_yesno(state))
		end

	-- Cell Attributes (no redraw). These attributes are only updated in the 
	-- display when you redraw.

	set_corner_title (title: STRING)
		-- Set title of the area between the line and column titles.
		do
			iup_open.set_attribute_id2(Current, "", 0, 0, title)
		end

	get_corner_title: STRING
		do
			Result := iup_open.get_attribute_id2(Current, "", 0, 0)
		end

	set_line_title (line: INTEGER; title: STRING)
		-- Set title of line.
		do
			iup_open.set_attribute_id2(Current, "", line, 0, title)
		end

	get_line_title (line: INTEGER): STRING
		do
			Result := iup_open.get_attribute_id2(Current, "", line, 0)
		end

	set_column_title (column: INTEGER; title: STRING)
		-- Set title of column.
		do
			iup_open.set_attribute_id2(Current, "", 0, column, title)
		end

	get_column_title (column: INTEGER): STRING
		do
			Result := iup_open.get_attribute_id2(Current, "", 0, column)
		end

	set_text_at_cell (text: STRING; line, column: INTEGER)
		-- Set text of the cell located in line and column.
		do
			iup_open.set_attribute_id2(Current, "", line, column, text)
		end

	get_text_at_cell (line, column: INTEGER): STRING
		do
			Result := iup_open.get_attribute_id2(Current, "", line, column)
		end

	-- The following features are valid only in normal mode.

	set_alignment_at (line_align, col_align: STRING; line, column: INTEGER)
		-- Alignment of the cell value in line and column. Where line_align can 
		-- be "ATOP", "ACENTER" or "ABOTTOM", and col_align can be "ALEFT", 
		-- "ACENTER" or "ARIGHT". Default will use the column alignment 
		-- and the line alignment.
		require
			is_valid_lin_align (line_align)
			is_valid_col_align (col_align)
			line >= 0
			column >= 0
		local
			str: STRING
		do
			create str.copy(line_align)
			str.append_string(":")
			str.append_string(col_align)

			iup_open.set_attribute_id2(Current, "ALIGN", line, column, str)
		end

	get_alignment_at (line, column: INTEGER): TUPLE[STRING, STRING]
		-- Return the alignment at the cell in format [line_align, col_align]
		local
			str: STRING
		do
			str := iup_open.get_attribute_id2(Current, "ALIGN", line, column)

			Result := components_of_alignment (str)
		end

	set_type_cell_at (type: STRING; line, column: INTEGER)
		-- Can be "TEXT", "COLOR", "FILL", or "IMAGE". When type is "COLOR" the 
		-- cell value is interpreted as a color and a rectangle with the color is 
		-- drawn inside the cell instead of the text (the foreground color of the 
		-- cell is ignored). When type is "FILL" the cell value is interpreted as 
		-- percentage and a rectangle showing the percentage in the foreground 
		-- color is drawn. When type is "IMAGE" the cell value is interpreted as 
		-- an image name, and if an image exist with that name is drawn (the name 
		-- can NOT be of a Windows resource or GTK stock image). Only "TEXT" and 
		-- "IMAGE" are affected by alignment attributes. Default: "TEXT".
		require
			is_valid_type_cell (type)
			line > 0
			column > 0
		do
			iup_open.set_attribute_id2(Current, "TYPE", line, column, type)
		end

	get_type_cell_at (line, column: INTEGER): STRING
		do
			Result := iup_open.get_attribute_id2(Current, "TYPE", line, column)
		end

	set_type_column (type: STRING; column: INTEGER)
		require
			is_valid_type_cell (type)
			column > 0
		do
			iup_open.set_attribute_id2(Current, "TYPE", -10, column, type)
		end

	get_type_column (column: INTEGER): STRING
		do
			Result := iup_open.get_attribute_id2(Current, "TYPE", -10, column)
		end

	set_type_line (type: STRING; line: INTEGER)
		require
			is_valid_type_cell (type)
			line > 0
		do
			iup_open.set_attribute_id2(Current, "TYPE", line, -10, type)
		end

	get_type_line (line: INTEGER): STRING
		do
			Result := iup_open.get_attribute_id2(Current, "TYPE", line, -10)
		end

	set_background_color_at (red, green, blue, line, column: INTEGER)
		-- When more than one attribute are defined, the background color will be 
		-- selected following this priority: cell background color, 
		-- line background color, column background color, and last 
		-- background color.
		--
		-- Default background color is the global attribute TXTBGCOLOR for cells 
		-- and the parent's background for titles.
		-- Since the matrix control can be larger than the matrix itself, the 
		-- empty area will always be filled with the parent's 
		-- background color.
		require
			line >= 0
			column >= 0
		do
			iup_open.set_attribute_id2(Current, "BGCOLOR", line, column, rgb_to_string(red, green, blue))
		end

	get_background_color_at (line, column: INTEGER): TUPLE[INTEGER, INTEGER, INTEGER]
		require
			line >= 0
			column >= 0
		local
			str: STRING
		do
			str := iup_open.get_attribute_id2(Current, "BGCOLOR", line, column)

			Result := string_to_rgb(str)
		end

	set_background_color_at_column (red, green, blue, column: INTEGER)
		require
			column >= 0
		do
			iup_open.set_attribute_id2(Current, "BGCOLOR", -10, column, rgb_to_string(red, green, blue))
		end

	get_background_color_at_column (column: INTEGER): TUPLE[INTEGER, INTEGER, INTEGER]
		require
			column >= 0
		local
			str: STRING
		do
			str := iup_open.get_attribute_id2(Current, "BGCOLOR", -10, column)

			Result := string_to_rgb(str)
		end

	set_background_color_at_line (red, green, blue, line: INTEGER)
		require
			line >= 0
		do
			iup_open.set_attribute_id2(Current, "BGCOLOR", line, -10, rgb_to_string(red, green, blue))
		end

	get_background_color_at_line (line: INTEGER): TUPLE[INTEGER, INTEGER, INTEGER]
		require
			line >= 0
		local
			str: STRING
		do
			str := iup_open.get_attribute_id2(Current, "BGCOLOR", line, -10)

			Result := string_to_rgb(str)
		end

	set_foreground_color_at (red, green, blue, line, column: INTEGER)
		-- When more than one attribute are defined, the foreground color will be
		-- selected following this priority: cell foreground color, 
		-- line foreground color, column foreground color, and last 
		-- foreground color.
		--
		-- Default foreground color is the global attribute TXTFGCOLOR for cells 
		-- and the parent's foreground for titles.
		-- Since the matrix control can be larger than the matrix itself, the 
		-- empty area will always be filled with the parent's 
		-- foreground color.
		require
			line >= 0
			column >= 0
		do
			iup_open.set_attribute_id2(Current, "FGCOLOR", line, column, rgb_to_string(red, green, blue))
		end

	get_foreground_color_at (line, column: INTEGER): TUPLE[INTEGER, INTEGER, INTEGER]
		require
			line >= 0
			column >= 0
		local
			str: STRING
		do
			str := iup_open.get_attribute_id2(Current, "FGCOLOR", line, column)

			Result := string_to_rgb(str)
		end

	set_foreground_color_at_column (red, green, blue, column: INTEGER)
		require
			column >= 0
		do
			iup_open.set_attribute_id2(Current, "FGCOLOR", -10, column, rgb_to_string(red, green, blue))
		end

	get_foreground_color_at_column (column: INTEGER): TUPLE[INTEGER, INTEGER, INTEGER]
		require
			column >= 0
		local
			str: STRING
		do
			str := iup_open.get_attribute_id2(Current, "FGCOLOR", -10, column)

			Result := string_to_rgb(str)
		end

	set_foreground_color_at_line (red, green, blue, line: INTEGER)
		require
			line >= 0
		do
			iup_open.set_attribute_id2(Current, "FGCOLOR", line, -10, rgb_to_string(red, green, blue))
		end

	get_foreground_color_at_line (line: INTEGER): TUPLE[INTEGER, INTEGER, INTEGER]
		require
			line >= 0
		local
			str: STRING
		do
			str := iup_open.get_attribute_id2(Current, "FGCOLOR", line, -10)

			Result := string_to_rgb(str)
		end

	set_font_at (font: STRING; line, column: INTEGER)
		-- This attribute must be set before the control is showed. It affects 
		-- the calculation of the size of all the matrix cells. The cell size is 
		-- always calculated from the base font attribute.
		require
			non_negative: line >= 0
							  column >= 0
		do
			iup_open.set_attribute_id2(Current, "FONT", line, column, font)
		end

	set_font_at_column (font: STRING; column: INTEGER)
		require
			non_negative: column >= 0
		do
			iup_open.set_attribute_id2(Current, "FONT", -10, column, font)
		end

	set_font_at_line (font: STRING; line: INTEGER)
		require
			non_negative: line >= 0
		do
			iup_open.set_attribute_id2(Current, "FONT", line, -10, font)
		end

	set_frame_color (red, green, blue: INTEGER)
		-- Sets the color to be used in the frame lines. (inheritable)
		do
			iup_open.set_attribute(Current, "FRAMECOLOR", rgb_to_string(red, green, blue))
		end

	set_vertical_frame_color_at (red, green, blue, line, column: INTEGER)
		-- Color of the vertical right frame line of the cell. When not defined 
		-- the verticel frame color is used. For a title column cell (column=0) 
		-- defines right and left frames. If value is "BGCOLOR" the frame line is 
		-- not drawn.
		require
			line >= 0
			column >= 0
		do
			iup_open.set_attribute_id2(Current, "FRAMEVERTCOLOR", line, column,
			                           rgb_to_string(red, green, blue))
		end

	set_vertical_frame_color_at_column (red, green, blue, column: INTEGER)
		-- Same as "set_vertical_frame_color_at" but for all the cells of the 
		-- column.
		require
			column >= 0
		do
			iup_open.set_attribute_id2(Current, "FRAMEVERTCOLOR", -10, column,
			                           rgb_to_string(red, green, blue))
		end

	set_frame_title_vertical_color_at_line (red, green, blue, line: INTEGER)
		-- Color of the vertical left frame line of the title cell. When not 
		-- defined the FRAMEVERTCOLORL:0 is used.
		require
			line >= 0
		do
			iup_open.set_attribute_id2(Current, "FRAMETITLEVERTCOLOR", line, 0,
			                           rgb_to_string(red, green, blue))
		end

	set_frame_title_vertical_color (red, green, blue: INTEGER)
		-- Color of the vertical left frame line for all the title cells. When 
		-- not defined the FRAMEVERTCOLORL:0 is used.
		do
			iup_open.set_attribute_id2(Current, "FRAMETITLEVERTCOLOR", -10, 0,
			                           rgb_to_string(red, green, blue))
		end

	set_horizontal_frame_color_at (red, green, blue, line, column: INTEGER)
		-- Color of the horizontal bottom frame line of the cell. When not defined
		-- the verticel frame color is used. For a title line cell (line=0) 
		-- defines bottom and top frames. If value is "BGCOLOR" the frame line is 
		-- not drawn.
		require
			line >= 0
			column >= 0
		do
			iup_open.set_attribute_id2(Current, "FRAMEHORIZCOLOR", line, column,
			                           rgb_to_string(red, green, blue))
		end

	set_horizontal_frame_color_at_line (red, green, blue, line: INTEGER)
		-- Same as "set_horizontal_frame_color_at" but for all the cells of the 
		-- line.
		require
			line >= 0
		do
			iup_open.set_attribute_id2(Current, "FRAMEHORIZCOLOR", line, -10,
			                           rgb_to_string(red, green, blue))
		end

	set_frame_title_horizontal_color_at_column (red, green, blue, column: INTEGER)
		-- Color of the horizontal top frame line of the title cell. When not 
		-- defined the FRAMEHORIZCOLOR0:C is used.
		require
			column >= 0
		do
			iup_open.set_attribute_id2(Current, "FRAMETITLEHORIZCOLOR", 0, column,
			                           rgb_to_string(red, green, blue))
		end

	set_frame_title_horizontal_color (red, green, blue: INTEGER)
		-- Color of the horizontal top frame line of all title cells. When not 
		-- defined the FRAMEHORIZCOLOR0:C is used.
		do
			iup_open.set_attribute_id2(Current, "FRAMETITLEHORIZCOLOR", 0, -10,
			                           rgb_to_string(red, green, blue))
		end

	set_frame_title_highlight (state: BOOLEAN)
		-- By default the title cells will have a bright line at left and top to 
		-- configure a raise appearance. Default: True.
		do
			iup_open.set_attribute(Current, "FRAMETITLEHIGHLIGHT", boolean_to_yesno(state))
		end

	set_frame_border (state: BOOLEAN)
		-- Show a fixed border (non scrollable) of 1 pixel around the matrix 
		-- visible area using FRAMECOLOR. It is drawn after the matrix cells are 
		-- drawn. Default: False. 
		do
			iup_open.set_attribute(Current, "FRAMEBORDER", boolean_to_yesno(state))
		end

	set_resize_matrix_color (red, green, blue: INTEGER)
		-- Color used by the column resize feedback. Default: "102 102 102".
		do
			iup_open.set_attribute(Current, "RESIZEMATRIXCOLOR", rgb_to_string(red, green, blue))
		end

	set_toggle_value_at (value: STRING; line, column: INTEGER)
		-- Value of the toggle inside the cell. The toggle is shown only if the 
		-- DROPCHECK_CB returns IUP_CONTINUE for the cell. When the toggle is 
		-- interactively change the TOGGLEVALUE_CB callback is called.
		require
			non_negative: line >= 0
							  column >= 0
		do
			iup_open.set_attribute_id2(Current, "TOGGLEVALUE", line, column, value)
		end

	get_toggle_value_at (line, column: INTEGER): STRING
		require
			non_negative: line >= 0
							  column >= 0
		do
			Result := iup_open.get_attribute_id2 (Current, "TOGGLEVALUE", line, column)
		end

	set_value (value: STRING)
		-- Allows setting the value of the current cell. Is the same as obtaining 
		-- the current cell line and column with "get_focus_cell", and then using 
		-- them with "get_text_at_cell" to get text in the cell. But when updated 
		-- or retrieved during cell editing, the edit control will be updated or 
		-- consulted instead of the matrix cell. When retrieved inside the 
		-- EDITION_CB callback when mode is 0, then the return value is the new 
		-- value that will be updated in the cell.
		do
			iup_open.set_attribute(Current, "VALUE", value)
		end

	get_value: STRING
		-- When retrieved during cell editing, the edit control will be  
		-- consulted instead of the matrix cell. When retrieved inside the 
		-- EDITION_CB callback when mode is 0, then the return value is the new 
		-- value that will be updated in the cell.
		do
			Result := iup_open.get_attribute(Current, "VALUE")
		end

	-- Read only (Cell Attributes)

	get_cell_at (line, column: INTEGER): STRING
		-- Returns the displayed cell value. Returns Void if the cell does not 
		-- exists, or it is not visible, or the element is not mapped.
		require
			non_negative: line >= 0
							  column >= 0
		do
			Result := iup_open.get_attribute_id2(Current, "CELL", line, column)
		end

	get_cell_background_color_at (line, column: INTEGER): TUPLE[INTEGER, INTEGER, INTEGER]
		-- Returns the actual cell background color. Returns Void if the cell 
		-- does not exists, or it is not visible, or the element is not mapped.
		require
			non_negative: line >= 0
							  column >= 0
		local
			str: STRING
		do
			str := iup_open.get_attribute_id2(Current, "CELLBGCOLOR", line, column)

			Result := string_to_rgb(str)
		end

	get_cell_foreground_color_at (line, column: INTEGER): TUPLE[INTEGER, INTEGER, INTEGER]
		-- Returns the actual cell foreground color. Returns Void if the cell 
		-- does not exists, or it is not visible, or the element is not mapped.
		require
			non_negative: line >= 0
							  column >= 0
		local
			str: STRING
		do
			str := iup_open.get_attribute_id2(Current, "CELLFGCOLOR", line, column)

			Result := string_to_rgb(str)
		end

	get_cell_font_at (line, column: INTEGER): STRING
		-- Returns the actual cell font. Returns NULL if the cell does not 
		-- exists, or it is not visible, or the element is not mapped.
		require
			non_negative: line >= 0
							  column >= 0
		do
			Result := iup_open.get_attribute_id2(Current, "CELLFONT", line, column)
		end

	get_cell_type_at (line, column: INTEGER): STRING
		-- Returns the actual cell type. Returns NULL if the cell does not 
		-- exists, or it is not visible, or the element is not mapped.
		require
			non_negative: line >= 0
							  column >= 0
		do
			Result := iup_open.get_attribute_id2(Current, "CELLTYPE", line, column)
		end

	get_cell_frame_horizontal_color_at (line, column: INTEGER): TUPLE[INTEGER, INTEGER, INTEGER]
		-- Returns the actual cell frame horizontal color. Returns NULL if the 
		-- cell does not exists, or it is not visible, the element is not mapped, 
		-- or the color is transparent.
		require
			non_negative: line >= 0
							  column >= 0
		local
			str: STRING
		do
			str := iup_open.get_attribute_id2(Current, "CELLFRAMEHORIZCOLOR", line, column)

			Result := string_to_rgb(str)
		end

	get_cell_frame_vertical_color_at (line, column: INTEGER): TUPLE[INTEGER, INTEGER, INTEGER]
		-- Returns the actual cell frame vertical color. Returns NULL if the 
		-- cell does not exists, or it is not visible, the element is not mapped, 
		-- or the color is transparent.
		require
			non_negative: line >= 0
							  column >= 0
		local
			str: STRING
		do
			str := iup_open.get_attribute_id2(Current, "CELLFRAMEVERTCOLOR", line, column)

			Result := string_to_rgb(str)
		end

	get_cell_alignment_at (line, column: INTEGER): STRING
		-- Returns the actual cell text aligment, including lin and col 
		-- variations. Returns NULL if the cell does not exists, or it is not 
		-- visible, or the element is not mapped.
		require
			non_negative: line >= 0
							  column >= 0
		do
			Result := iup_open.get_attribute_id2(Current, "CELLALIGNMENT", line, column)
		end

	get_cell_offset_at (line, column: INTEGER): TUPLE[INTEGER, INTEGER]
		-- Returns the cell computed offset in pixels from the top-left corner of 
		-- the matrix, in the format [X, Y]. Returns Void if the cell does not 
		-- exists, or it is not visible, or the element is not mapped. It will 
		-- only return a valid result if the cell has already been displayed. 
		-- They are similar to the parameters of the DRAW_CB callback but they do 
		-- NOT include the decorations.
		require
			non_negative: line >= 0
							  column >= 0
		local
			str: STRING
		do
			str := iup_open.get_attribute_id2(Current, "CELLOFFSET", line, column)
			Result := components_of_size (str)
		end

	get_cell_size_at (line, column: INTEGER): TUPLE[INTEGER, INTEGER]
		-- Returns the cell computed size in pixels, in the format [W, H]. 
		-- Returns Void if the cell does not exists, or the element is not 
		-- mapped. It will only return a valid result if the cell has already 
		-- been displayed. They are similar to the parameters of the DRAW_CB 
		-- callback but they do NOT include the decorations.
		require
			non_negative: line >= 0
							  column >= 0
		local
			str: STRING
		do
			str := iup_open.get_attribute_id2(Current, "CELLSIZE", line, column)
			Result := components_of_size (str)
		end

	-- Column/Line Only Attributes (no redraw)

	set_horizontal_alignment_at_column (value: STRING; column: INTEGER)
		-- Horizontal alignment of the cells in column (column >= 0) for lines 
		-- that greater than 0. Can be: "ALEFT", "ACENTER" or "ARIGHT". Default: 
		-- "ALEFT" for column=0 and "ACENTER" for column>0. Before checking the 
		-- default value it will check the "ALIGNMENT" attribute value. If the 
		-- text do not fit in the cell then the alignment is changed to "ALEFT".
		require
			valid: column >= 0
					 is_valid_col_align(value)
		do
			iup_open.set_attribute_id(Current, "ALIGNMENT", column, value)
		end

	get_horizontal_alignment_at_column (column: INTEGER): STRING
		require
			non_negative: column >= 0
		do
			Result := iup_open.get_attribute_id(Current, "ALIGNMENT", column)
		end

	set_alignment_line_0 (value: STRING)
		-- Horizontal alignment of all the cells in line 0. Default is "ACENTER".
		require
			valid: is_valid_col_align(value)
		do
			iup_open.set_attribute(Current, "ALIGNMENTLIN0", value)
		end

	get_alignment_line_0: STRING
		do
			Result := iup_open.get_attribute(Current, "ALIGNMENTLIN0")
		end

	set_vertical_alignment_at_line (value: STRING; line: INTEGER)
		-- Vertical alignment of the cells in line (line >= 0) for all columns. 
		-- Can be: "ATOP", "ACENTER" or "ABOTTOM". Default is "ACENTER".
		require
			valid: line >= 0
					 is_valid_lin_align(value)
		do
			iup_open.set_attribute_id(Current, "LINEALIGNMENT", line, value)
		end

	get_vertical_alignment_at_line (line: INTEGER): STRING
		require
			non_negative: line >= 0
		do
			Result := iup_open.get_attribute_id(Current, "LINEALIGNMENT", line)
		end

	set_sort_sign_at_column (value: STRING; column: INTEGER)
		-- Shows a sort sign (up or down arrow) in the column (column >= 0) 
		-- title. Possible values: "UP", "DOWN" and "NO". Default: NO.
		require
			valid: column >= 0
					 is_valid_sort_sign(value)
		do
			iup_open.set_attribute_id(Current, "SORTSIGN", column, value)
		end

	get_sort_sign_at_column (column: INTEGER): STRING
		do
			Result := iup_open.get_attribute_id(Current, "SORTSIGN", column)
		end

	set_sort_image_down (name: STRING)
		-- Sort sign image name. Use "set_attribute_handle" associate an image to 
		-- a name. See also IUP_IMAGE. By default an internal image will be used.
		do
			iup_open.set_attribute(Current, "SORTIMAGEDOWN", name)
		end

	get_sort_image_down: STRING
		do
			Result := iup_open.get_attribute(Current, "SORTIMAGEDOWN")
		end

	set_sort_image_up (name: STRING)
		-- Sort sign image name. Use "set_attribute_handle" associate an image to 
		-- a name. See also IUP_IMAGE. By default an internal image will be used.
		do
			iup_open.set_attribute(Current, "SORTIMAGEUP", name)
		end

	get_sort_image_up: STRING
		do
			Result := iup_open.get_attribute(Current, "SORTIMAGEUP")
		end

	-- Size Attributes

	set_limit_expand (state: BOOLEAN)
		-- Limit expansion to the maximum size that shows all cells. This will 
		-- set the MAXSIZE attribute to match the natural size of the matrix when 
		-- all cells are visible. When the scrollbars have *AUTOHIDE=True, the 
		-- maximum size will not include the scrollbars.
		do
			iup_open.set_attribute(Current, "LIMITEXPAND", boolean_to_yesno(state))
		end

	is_limit_expand: BOOLEAN
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "LIMITEXPAND")
			Result := yesno_to_boolean(str)
		end

	set_resize_matrix (state: BOOLEAN)
		-- Defines if the width of a column can be interactively changed. When 
		-- this is possible, the user can change the size of a column by dragging 
		-- the column title right border. Default: "False" (does not allow 
		-- interactive width change).
		do
			iup_open.set_attribute(Current, "RESIZEMATRIX", boolean_to_yesno(state))
		end

	is_resize_matrix: BOOLEAN
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "RESIZEMATRIX")
			Result := yesno_to_boolean(str)
		end

	set_resize_drag (state: BOOLEAN)
		-- Resize the column while dragging. By default the column is resized 
		-- only when the mouse button is released, the resize feedback is a 
		-- simple vertical line. Works only when set_resize_matrix=True.
		-- Default: False.
		do
			iup_open.set_attribute(Current, "RESIZEDRAG", boolean_to_yesno(state))
		end

	set_use_title_size (state: BOOLEAN)
		-- Use the title size to define the cell size if necessary. See WIDTHn and
		-- HEIGHTn. Default: False.
		do
			iup_open.set_attribute(Current, "USETITLESIZE", boolean_to_yesno(state))
		end

	is_use_title_size: BOOLEAN
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "USETITLESIZE")
			Result := yesno_to_boolean(str)
		end

	-- Column Size Attributes

	set_width_at_column (width, column: INTEGER)
		-- Width of column n in SIZE units, where n is the number of the column 
		-- (n>=0). If the width value is 0, the column will not be shown on the 
		-- screen. It does not includes the decoration size occupied by the frame 
		-- lines.
		require
			non_negative: width >= 0
							  column >= 0
		do
			iup_open.set_attribute_id(Current, "WIDTH", column, width.to_string)
		end

	get_width_at_column (column: INTEGER): INTEGER
		require
			non_negative: column >= 0
		do
			Result := iup_open.get_attribute_id(Current, "WIDTH", column).to_integer
		end

	set_default_width (width: INTEGER)
		-- Default column width in SIZE units. Not used for the title column. 
		-- Default: 80 (width corresponding to 20 characters).
		require
			non_negative: width >= 0
		do
			iup_open.set_attribute(Current, "WIDTHDEF", width.to_string)
		end

	get_default_width: INTEGER
		do
			Result := iup_open.get_attribute(Current, "WIDTHDEF").to_integer
		end

	set_raster_width_at_column (width, column: INTEGER)
		-- Same as "set_width_at_column" but in pixels. Has lower priority than 
		-- "set_width_at_column".
		require
			non_negative: width >= 0
							  column >= 0
		do
			iup_open.set_attribute_id(Current, "RASTERWIDTH", column, width.to_string)
		end

	get_raster_width_at_column (column: INTEGER): INTEGER
		require
			non_negative: column >= 0
		do
			Result := iup_open.get_attribute_id(Current, "RASTERWIDTH", column).to_integer
		end

	set_min_width_at_column (width, column: INTEGER)
		-- When the column is interactively resized controls the minimum width of 
		-- the given column. If not defined the min width column is used.
		require
			non_negative: width >= 0
							  column >= 0
		do
			iup_open.set_attribute_id(Current, "MINCOLWIDTH", column, width.to_string)
		end

	set_default_min_width (width: INTEGER)
		require
			non_negative: width >= 0
		do
			iup_open.set_attribute(Current, "MINCOLWIDTHDEF", width.to_string)
		end

	-- Line Size Attributes

	set_height_at_line (height, line: INTEGER)
		-- Height of line n in SIZE units, where n is the number of the line 
		-- (n>=0). If the height value is 0, the line will not be shown on the 
		-- screen. It does not includes the decoration size occupied by the frame 
		-- lines.
		require
			non_negative: height >= 0
							  line >= 0
		do
			iup_open.set_attribute_id(Current, "HEIGHT", line, height.to_string)
		end

	get_height_at_line (line: INTEGER): INTEGER
		require
			non_negative: line >= 0
		do
			Result := iup_open.get_attribute_id(Current, "HEIGHT", line).to_integer
		end

	set_default_height (height: INTEGER)
		-- Default line height in SIZE units. Not used for the title line. 
		-- Default: 8 (height corresponding to 1 line).
		require
			non_negative: height >= 0
		do
			iup_open.set_attribute(Current, "HEIGHTDEF", height.to_string)
		end

	get_default_height: INTEGER
		do
			Result := iup_open.get_attribute(Current, "HEIGHTDEF").to_integer
		end

	set_raster_height_at_line (height, line: INTEGER)
		-- Same as "set_height_at_line" but in pixels. Has lower priority than 
		-- "set_height_at_line".
		require
			non_negative: height >= 0
							  line >= 0
		do
			iup_open.set_attribute_id(Current, "RASTERHEIGHT", line, height.to_string)
		end

	get_raster_height_at_line (line: INTEGER): INTEGER
		require
			non_negative: line >= 0
		do
			Result := iup_open.get_attribute_id(Current, "RASTERHEIGHT", line).to_integer
		end

	-- Number of Cells Attributes

	add_column (reference: INTEGER)
		-- Adds a new column to the matrix after the specified column. To insert 
		-- a column at the top of the spreadsheet, value 0 must be used. It can 
		-- be used in normal operation mode or in callback mode, but in callback 
		-- mode will not update cell values this must be done by the application. 
		-- Can NOT add a title column. Ignored if set before map.
		require
			non_negative: reference >= 0
		do
			iup_open.set_attribute(Current, "ADDCOL", reference.to_string)
		end

	add_columns (reference, count: INTEGER)
		-- The first number corresponds to the base column and the second number 
		-- corresponds to the number of columns to be added. It can be used in 
		-- normal operation mode or in callback mode, but in callback mode will 
		-- not update cell values this must be done by the application. To insert 
		-- columns at the top of the spreadsheet, value 0 must be used as 
		-- reference. Can NOT add a title column. Ignored if set before map. 
		require
			non_negative: reference >= 0
							  count > 0
		local
			str: STRING
		do
			str := reference.to_string
			str.append_string("-")
			str.append_string(count.to_string)

			iup_open.set_attribute(Current, "ADDCOL", str)
		end

	add_line (reference: INTEGER)
		-- Adds a new line to the matrix after the specified line. To insert a 
		-- line at the top of the spreadsheet, value 0 must be used. It can be 
		-- used in normal operation mode or in callback mode, but in callback 
		-- mode will not update cell values this must be done by the application. 
		-- Can NOT add a title line. Ignored if set before map. 
		require
			non_negative: reference >= 0
		do
			iup_open.set_attribute(Current, "ADDLIN", reference.to_string)
		end

	add_lines (reference, count: INTEGER)
		-- The first number corresponds to the base line and the second number 
		-- corresponds to the number of lines to be added. It can be used in 
		-- normal operation mode or in callback mode, but in callback mode will 
		-- not update cell values this must be done by the application. To insert 
		-- lines at the top of the spreadsheet, value 0 must be used.Can NOT 
		-- add a title line. Ignored if set before map. 
		require
			non_negative: reference >= 0
							  count > 0
		local
			str: STRING
		do
			str := reference.to_string
			str.append_string("-")
			str.append_string(count.to_string)

			iup_open.set_attribute(Current, "ADDLIN", str)
		end

	delete_column (reference: INTEGER)
		-- Removes the given column from the matrix. It can be used in normal 
		-- operation mode or in callback mode, but in callback mode will not 
		-- update cell values this must be done by the application. Can NOT 
		-- remove a title column, reference > 0. Ignored if set before map. 
		require
			reference > 0
		do
			iup_open.set_attribute(Current, "DELCOL", reference.to_string)
		end

	delete_columns (reference, count: INTEGER)
		-- The first number corresponds to the base column and the second number 
		-- corresponds to the number of columns to be removed. It can be used in 
		-- normal operation mode or in callback mode, but in callback mode will 
		-- not update cell values this must be done by the application. Can NOT 
		-- remove a title column, reference > 0. Ignored if set before map. 
		require
			reference > 0
			count > 0
		local
			str: STRING
		do
			str := reference.to_string
			str.append_string("-")
			str.append_string(count.to_string)
			
			iup_open.set_attribute(Current, "DELCOL", str)
		end

	delete_line (reference: INTEGER)
		-- Removes the given line from the matrix. It can be used in normal 
		-- operation mode or in callback mode, but in callback mode will not 
		-- update cell values this must be done by the application. Can NOT 
		-- remove a title line, reference > 0. Ignored if set before map. 
		require
			reference > 0
		do
			iup_open.set_attribute(Current, "DELLIN", reference.to_string)
		end

	delete_lines (reference, count: INTEGER)
		-- The first number corresponds to the base line and the second number 
		-- corresponds to the number of lines to be removed. It can be used in 
		-- normal operation mode or in callback mode, but in callback mode will 
		-- not update cell values this must be done by the application. Can NOT 
		-- remove a title line, reference > 0. Ignored if set before map. 
		require
			reference > 0
			count > 0
		local
			str: STRING
		do
			str := reference.to_string
			str.append_string("-")
			str.append_string(count.to_string)
			
			iup_open.set_attribute(Current, "DELLIN", str)
		end

	set_number_of_columns (count: INTEGER)
		-- Defines the number of columns in the matrix. Default: "0". It does not 
		-- include the title column. If changed after map will add empty cells or 
		-- discard cells at the end.
		require
			non_negative: count >= 0
		do
			iup_open.set_attribute(Current, "NUMCOL", count.to_string)
		end

	get_number_of_columns: INTEGER
		do
			Result := iup_open.get_attribute(Current, "NUMCOL").to_integer
		end

	set_number_of_visible_columns (count: INTEGER)
		-- When set defines the number of visible columns to be counted when 
		-- calculating the Natural size, not counting the title column. Not used 
		-- elsewhere. The Natural size will always include the title column if 
		-- any. Can be greater than the actual number of columns, so room will be 
		-- reserved for adding new columns without the need to resize the matrix. 
		-- Also it will always use the first columns of the matrix, except if 
		-- "set_visible_last_columns" is set to True then it will use the last 
		-- columns. The remaining columns will be accessible only by using the 
		-- scrollbar. Default: "4".
		require
			non_negative: count >= 0
		do
			iup_open.set_attribute(Current, "NUMCOL_VISIBLE", count.to_string)
		end

	get_number_of_visible_columns: INTEGER
		-- Returns the current number of visible columns, not including the non 
		-- scrollable columns.
		do
			Result := iup_open.get_attribute(Current, "NUMCOL_VISIBLE").to_integer
		end

	set_number_of_non_scrollable_columns (count: INTEGER)
		-- Number of columns that are non scrollable, not counting the title 
		-- column. Default: "0". It does not affect the "visible columns" 
		-- attribute behavior nor Natural size computation. It will always use 
		-- the first columns of the matrix. The cells appearance will be the same 
		-- of ordinary cells, and they can also receive the focus and be edited. 
		-- Must be less than the total number of columns.
		require
			non_negative: count >= 0
		do
			iup_open.set_attribute(Current, "NUMCOL_NOSCROLL", count.to_string)
		end

	set_visible_last_columns (state: BOOLEAN)
		do
			iup_open.set_attribute(Current, "NUMCOL_VISIBLE_LAST", boolean_to_yesno(state))
		end

	set_number_of_lines (count: INTEGER)
		-- Defines the number of lines in the matrix. Default: "0". It does not 
		-- include the title line. If changed after map will add empty cells or 
		-- discard cells at the end.
		require
			non_negative: count >= 0
		do
			iup_open.set_attribute(Current, "NUMLIN", count.to_string)
		end

	get_number_of_lines: INTEGER
		do
			Result := iup_open.get_attribute(Current, "NUMLIN").to_integer
		end

	set_number_of_visible_lines (count: INTEGER)
		-- When set defines the number of visible lines to be counted when 
		-- calculating the Natural size, not counting the title line. Not used 
		-- elsewhere. The Natural size will always include the title line if any. 
		-- Can be greater than the actual number of lines, so room will be 
		-- reserved for adding new lines without the need to resize the matrix. 
		-- Also it will always use the first lines of the matrix, except 
		-- "set_last_visible_columns" is set the True then it will use the last 
		-- lines. The remaining lines will be accessible only by using the 
		-- scrollbar.
		require
			non_negative: count >= 0
		do
			iup_open.set_attribute(Current, "NUMLIN_VISIBLE", count.to_string)
		end

	get_number_of_visible_lines: INTEGER
		-- Returns the current number of visible lines, not including the non 
		-- scrollable lines. Default: "3".
		do
			Result := iup_open.get_attribute(Current, "NUMLIN_VISIBLE").to_integer
		end

	set_number_of_non_scrollable_lines (count: INTEGER)
		-- Number of lines that are non scrollable, not counting the title line. 
		-- Default: "0". It does not affect the "visible lines" attribute 
		-- behavior nor Natural size computation. It will always use the first 
		-- lines of the matrix. The cells appearance will be the same of ordinary 
		-- cells, and they can also receive the focus and be edited. Must be less 
		-- than the total number of lines.
		require
			non_negative: count >= 0
		do
			iup_open.set_attribute(Current, "NUMLIN_NOSCROLL", count.to_string)
		end

	set_visible_last_lines (state: BOOLEAN)
		do
			iup_open.set_attribute(Current, "NUMLIN_VISIBLE_LAST", boolean_to_yesno(state))
		end

	set_no_scroll_as_title (state: BOOLEAN)
		-- Non scrollable lines and columns to look and behave as title cells.
		-- Default: "False".
		do
			iup_open.set_attribute(Current, "NOSCROLLASTITLE", boolean_to_yesno(state))
		end

	-- Mark Attributes

	set_mark_area_continuous
		-- Defines that the area to be interactively marked by the user must be 
		-- continuous, valid only if "mark multiple" is set to True. 
		-- Continuous is the default value.
		do
			iup_open.set_attribute(Current, "MARKAREA", "CONTINUOUS")
		end

	set_mark_area_not_continuous
		-- Defines that the area to be interactively marked by the user could be 
		-- continuous or not, valid only if "mark multiple" is set to True. 
		do
			iup_open.set_attribute(Current, "MARKAREA", "NOT_CONTINUOUS")
		end

	set_mark_at_title (state: BOOLEAN)
		-- A click at a title will mark a full line or a full column if they can 
		-- be marked. Default: "True".
		do
			iup_open.set_attribute(Current, "MARKATTITLE", boolean_to_yesno(state))
		end

	set_mark_mode_no
		-- No mark. This is the default value.
		do
			iup_open.set_attribute(Current, "MARKMODE", "NO")
		end

	set_mark_mode_lines
		-- Defines lines as the entity that can be marked.
		do
			iup_open.set_attribute(Current, "MARKMODE", "LIN")
		end

	set_mark_mode_columns
		-- Defines columns as the entity that can be marked.
		do
			iup_open.set_attribute(Current, "MARKMODE", "COL")
		end

	set_mark_mode_lines_and_columns
		-- Defines lines and columns as the entity that can be marked.
		do
			iup_open.set_attribute(Current, "MARKMODE", "LINCOL")
		end

	set_mark_mode_cell
		-- Defines cells as the entity that can be marked.
		do
			iup_open.set_attribute(Current, "MARKMODE", "CELL")
		end

	mark_cell (line, column: INTEGER)
		-- (no redraw) Even when mark mode is "lines", "columns" or "lines and 
		-- columns" you can specify a single cell address.
		require
			line > 0
			column > 0
		do
			iup_open.set_attribute_id2(Current, "MARK", line, column, "1")
		end

	unmark_cell (line, column: INTEGER)
		-- (no redraw)
		require
			line > 0
			column > 0
		do
			iup_open.set_attribute_id2(Current, "MARK", line, column, "0")
		end

	is_marked_cell (line, column: INTEGER): BOOLEAN
		require
			line > 0
			column > 0
		local
			str: STRING
		do
			str := iup_open.get_attribute_id2(Current, "MARK", line, column)

			Result := string_to_boolean(str)
		end

	mark_line (line: INTEGER)
		-- (no redraw)
		require
			line > 0
		do
			iup_open.set_attribute_id2(Current, "MARK", line, 0, "1")
		end

	unmark_line (line: INTEGER)
		-- (no redraw)
		require
			line > 0
		do
			iup_open.set_attribute_id2(Current, "MARK", line, 0, "0")
		end

	is_marked_line (line: INTEGER): BOOLEAN
		require
			line > 0
		local
			str: STRING
		do
			str := iup_open.get_attribute_id2(Current, "MARK", line, 0)

			Result := string_to_boolean(str)
		end

	mark_column (column: INTEGER)
		-- (no redraw)
		require
			column > 0
		do
			iup_open.set_attribute_id2(Current, "MARK", 0, column, "1")
		end

	unmark_column (column: INTEGER)
		-- (no redraw)
		require
			column > 0
		do
			iup_open.set_attribute_id2(Current, "MARK", 0, column, "0")
		end

	is_marked_column (column: INTEGER): BOOLEAN
		require
			column > 0
		local
			str: STRING
		do
			str := iup_open.get_attribute_id2(Current, "MARK", 0, column)

			Result := string_to_boolean(str)
		end

	clear_marks
		-- Clear all marks.
		do
			iup_open.set_attribute_null(Current, "MARKED")
		end

	mark_cells (values: FAST_ARRAY2[BOOLEAN])
		-- An array2 with number of lines x number of columns positions, 
		-- corresponding to all the cells in the matrix starting with all the 
		-- cells of the first line, then the second line and so on. All 
		-- the positions with True value will be marked.
		do
			iup_open.set_attribute(Current, "MARKED", array2_to_marks(values))
		end

	marked_cells: FAST_ARRAY2[BOOLEAN]
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "MARKED")
			
			if not str.first.is_equal('L') and
				not str.first.is_equal('C') then
				
				Result := marks_to_array2(str)
			end
		end

	mark_lines (values: FAST_ARRAY[BOOLEAN])
		do
			iup_open.set_attribute(Current, "MARKED", "L" + array_to_marks(values))
		end

	marked_lines: FAST_ARRAY[BOOLEAN]
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "MARKED")

			if str.first.is_equal('L') then
				str.remove_first

				Result := marks_to_array(str, get_number_of_lines)
			end
		end

	mark_columns (values: FAST_ARRAY[BOOLEAN])
		do
			iup_open.set_attribute(Current, "MARKED", "C" + array_to_marks(values))
		end

	marked_columns: FAST_ARRAY[BOOLEAN]
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "MARKED")

			if str.first.is_equal('C') then
				str.remove_first

				Result := marks_to_array(str, get_number_of_columns)
			end
		end

	set_mark_multiple (state: BOOLEAN)
		-- Defines if more than one entity defined by mark mode can be 
		-- interactively marked. Default: "False".
		do
			iup_open.set_attribute(Current, "MARKMULTIPLE", boolean_to_yesno(state))
		end

	-- Merge Attributes

	merge_range (line1, column1, line2, column2: INTEGER)
		-- Merge a range of cells starting from the given "linne1:column1", and 
		-- ending at the given "line2:column2". Title cells can also be merge but 
		-- only among them, i.e. in the line of column titles (L=0) can only 
		-- merge columns, and in the column of line titles (C=0) can only merge 
		-- lines. The corner cell (0:0) can not be merged with any other cell. 
		-- Only cells that are not already merged can be merged into a range.
		require
			non_negative: line1 >= 0
							  column1 > 0
							  line2 >= 0
							  column2 >= 0
		local
			str: STRING
		do
			str := line2.to_string
			str.append_string(":")
			str.append_string(column2.to_string)

			iup_open.set_attribute_id2(Current, "MERGE", line1, column2, str)
		end

	is_merged_cell (line, column: INTEGER): BOOLEAN
		-- Returns if the given cell belongs to a merged range.
		require
			non_negative: line >= 0
							  column > 0
		local
			str: STRING
		do
			str := iup_open.get_attribute_id2(Current, "MERGE", line, column)

			Result := yesno_to_boolean(str)
		end

	split_a_merged_range (line, column: INTEGER)
		-- Split a merged range. value is a cell "lin:col" than belongs to the 
		-- range, any cell of the range can be used.
		require
			non_negative: line >= 0
							  column > 0
		local
			str: STRING
		do
			str := line.to_string
			str.append_string(":")
			str.append_string(column.to_string)

			iup_open.set_attribute(Current, "MERGESPLIT", str)
		end

	range_start (line, column: INTEGER): TUPLE[INTEGER, INTEGER]
		-- Returns the start cell of the range given a cell that belongs to the 
		-- range, any cell of the range can be used.
		local
			str: STRING
		do
			str := iup_open.get_attribute_id2(Current, "MERGEDSTART", line, column)

			Result := components_of (str, ':')
		end

	range_end (line, column: INTEGER): TUPLE[INTEGER, INTEGER]
		-- Returns the end cell of the range given a cell that belongs to the 
		-- range, any cell of the range can be used.
		local
			str: STRING
		do
			str := iup_open.get_attribute_id2(Current, "MERGEDEND", line, column)

			Result := components_of (str, ':')
		end

	-- Action Attributes

	clear_all_attributes
		-- Clear all cell attributes, all lines and column attributes are also 
		-- cleared.	
		do
			iup_open.set_attribute(Current, "CLEARATTRIB", "ALL")			
		end

	clear_all_attributes_except_contents
		-- Clear all cell attributes, except titles.
		do
			iup_open.set_attribute(Current, "CLEARATTRIB", "CONTENTS")	
		end

	clear_all_attributes_at_marked_cells
		-- Clear all cell attributes at selected cells.
		do
			iup_open.set_attribute(Current, "CLEARATTRIB", "MARKED")	
		end

	clear_all_attributes_at_interval (line1, column1, line2, column2: INTEGER)
		-- Clear all cell attributes in the interval starting at cell 1 
		-- and ending at cell 2.
		require
			line1 >= 0
			column1 >= 0
			line2 >= 0
			column2 >= 0
		local
			str: STRING
		do
			str := line2.to_string
			str.append_string(":")
			str.append_string(column2.to_string)

			iup_open.set_attribute_id2(Current, "CLEARATTRIB", line1, column1, str)
		end

	clear_all_line_attributes_at_interval (line, column1, column2: INTEGER)
		-- Clear the cell attributes in line at interval "column1-column2". When 
		-- a full line is specified, all line attributes are also cleared.
		require
			line >= 0
			column1 >= 0
			column2 >= 0
		local
			str: STRING
		do
			str := column1.to_string
			str.append_string("-")
			str.append_string(column2.to_string)

			iup_open.set_attribute_id2(Current, "CLEARATTRIB", line, -10, str)
		end

	clear_all_column_attributes_at_interval (column, line1, line2: INTEGER)
		-- Clear the cell attributes in column C at interval "line1-line2". When 
		-- a full column is specified, all column attributes are also cleared, 
		-- including alignment and sort sign.
		require
			column >= 0
			line1 >= 0
			line2 >= 0
		local
			str: STRING
		do
			str := line1.to_string
			str.append_string("-")
			str.append_string(line2.to_string)

			iup_open.set_attribute_id2(Current, "CLEARATTRIB", -10, column, str)
		end

	clear_all_values
		-- Clear all values.
		do
			iup_open.set_attribute(Current, "CLEARVALUE", "ALL")			
		end

	clear_all_values_except_contents
		-- Clear all values, except titles.
		do
			iup_open.set_attribute(Current, "CLEARVALUE", "CONTENTS")	
		end

	clear_all_values_at_marked_cells
		-- Clear all values at selected cells.
		do
			iup_open.set_attribute(Current, "CLEARVALUE", "MARKED")	
		end

	clear_all_values_at_interval (line1, column1, line2, column2: INTEGER)
		-- Clear all values at interval starting at cell 1 and 
		-- ending at cell 2.
		require
			line1 >= 0
			column1 >= 0
			line2 >= 0
			column2 >= 0
		local
			str: STRING
		do
			str := line2.to_string
			str.append_string(":")
			str.append_string(column2.to_string)

			iup_open.set_attribute_id2(Current, "CLEARVALUE", line1, column1, str)
		end

	clear_all_line_values_at_interval (line, column1, column2: INTEGER)
		-- Clear all values at line in the interval "column1-column2".
		require
			line >= 0
			column1 >= 0
			column2 >= 0
		local
			str: STRING
		do
			str := column1.to_string
			str.append_string("-")
			str.append_string(column2.to_string)

			iup_open.set_attribute_id2(Current, "CLEARVALUE", line, -10, str)
		end

	clear_all_column_values_at_interval (column, line1, line2: INTEGER)
		-- Clear all values at column in the interval "line1-line2".
		require
			column >= 0
			line1 >= 0
			line2 >= 0
		local
			str: STRING
		do
			str := line1.to_string
			str.append_string("-")
			str.append_string(line2.to_string)

			iup_open.set_attribute_id2(Current, "CLEARVALUE", -10, column, str)
		end

	copy_column_to (source_column, target_column: INTEGER)
		-- Copy the values and attributes from source_column to target_column.
		require
			source_column >= 0
			target_column >= 0
		do
			iup_open.set_attribute_id(Current, "COPYCOL", source_column,
			                          target_column.to_string)
		end

	copy_line_to (source_line, target_line: INTEGER)
		-- Copy the values and attributes from source_line to target_line.
		require
			source_line >= 0
			target_line >= 0
		do
			iup_open.set_attribute_id(Current, "COPYLIN", source_line,
			                          target_line.to_string)
		end

	fit_to_size_lines
		-- Force lines sizes so the matrix visible size fit in its current size. 
		-- number of visible lines/columns are considered when fitting and they 
		-- are not changed, only the raster width and raster height attributes 
		-- are changed. But if any of the raster width/height attributes where 
		-- already set, then they will not be changed. If the matrix is resized 
		-- then it must be set again to obtain the same result, but before doing 
		-- that set to Void all the raster width/height attributes that you want 
		-- to be changed.
		do
			iup_open.set_attribute(Current, "FITTOSIZE", "LINES")
		end

	fit_to_size_columns
		-- Force columns sizes so the matrix visible size fit in its current size.
		-- number of visible lines/columns are considered when fitting and they 
		-- are not changed, only the raster width and raster height attributes 
		-- are changed. But if any of the raster width/height attributes where 
		-- already set, then they will not be changed. If the matrix is resized 
		-- then it must be set again to obtain the same result, but before doing 
		-- that set to Void all the raster width/height attributes that you want 
		-- to be changed.
		do
			iup_open.set_attribute(Current, "FITTOSIZE", "COLUMNS")
		end

	fit_to_size_lines_and_columns
		-- Force lines and columns sizes so the matrix visible size fit in its 
		-- current size. number of visible lines/columns are considered when 
		-- fitting and they are not changed, only the raster width and raster 
		-- height attributes are changed. But if any of the raster width/height 
		-- attributes where already set, then they will not be changed. If the 
		-- matrix is resized then it must be set again to obtain the same result, 
		-- but before doing that set to Void all the raster width/height 
		-- attributes that you want to be changed.
		do
			iup_open.set_attribute(Current, "FITTOSIZE", "YES")
		end

	set_fit_maximum_width_at_column (value, column: INTEGER)
		-- The maximum width of the column.
		require
			value > 0
			column >= 0
		do
			iup_open.set_attribute_id(Current, "FITMAXWIDTH", column, value.to_string)
		end

	set_fit_maximum_height_at_line (value, line: INTEGER)
		-- The maximum height of the line.
		require
			value > 0
			line >= 0
		do
			iup_open.set_attribute_id(Current, "FITMAXHEIGHT", line, value.to_string)
		end

	fit_to_text_at_column (column: INTEGER)
		-- It will fit the largest text in the given column.
		require
			column >= 0
		do
			iup_open.set_attribute(Current, "FITTOTEXT", "C" + column.to_string) 
		end

	fit_to_text_at_line (line: INTEGER)
		-- It will fit the largest text in the given line.
		require
			line >= 0
		do
			iup_open.set_attribute(Current, "FITTOTEXT", "L" + line.to_string)
		end

	move_column_to (origin, target: INTEGER)
		-- Move the values and attributes from column origin to the target 
		-- column. Internally will use 'add column + copy column + 
		-- delete column' to perform the move so it is limited to those features 
		-- restrictions. It can be used in normal operation mode or in callback 
		-- mode, but in callback mode will not update cell values, this must be 
		-- done by the application.
		require
			origin > 0
			target >= 0
		do
			iup_open.set_attribute_id(Current, "MOVECOL", origin, target.to_string)
		end

	move_line_to (origin, target: INTEGER)
		-- Move the values and attributes from line origin to the target 
		-- line. Internally will use 'add line + copy line + 
		-- delete line' to perform the move so it is limited to those features 
		-- restrictions. It can be used in normal operation mode or in callback 
		-- mode, but in callback mode will not update cell values, this must be 
		-- done by the application.
		require
			origin > 0
			target >= 0
		do
			iup_open.set_attribute_id(Current, "MOVELIN", origin, target.to_string)
		end

	redraw_all
		-- Inform the matrix that the data has changed, and it must be redrawn.
		-- No redraw is done when the application change text at some 
		-- cell, or the alignment, back/fore ground color, font, value, 
		-- frame color or mark. Global and size attributes always automatically 
		-- redraw the matrix. The same applies for other redraw features.
		do
			iup_open.set_attribute(Current, "REDRAW", "ALL")
		end

	redraw_line (line: INTEGER)
		-- Inform the matrix that the line data has changed, and it must be 
		-- redrawn. 	
		require
			line >= 0
		do
			iup_open.set_attribute(Current, "REDRAW", "L" + line.to_string)
		end

	redraw_column (column: INTEGER)
		-- Inform the matrix that the column data has changed, and it must be 
		-- redrawn. 	
		require
			column >= 0
		do
			iup_open.set_attribute(Current, "REDRAW", "C" + column.to_string)
		end

	redraw_lines_in_region (start_line, end_line: INTEGER)
		-- Inform the matrix that the data in the region has changed, and it must 
		-- be redrawn. 
		require
			start_line >= 0
			end_line > 0
		do
			iup_open.set_attribute(Current, "REDRAW", "L" + start_line.to_string +
				"-" + end_line.to_string)
		end

	redraw_columns_in_region (start_column, end_column: INTEGER)
		-- Inform the matrix that the data in the region has changed, and it must 
		-- be redrawn. 
		require
			start_column >= 0
			end_column > 0
		do
			iup_open.set_attribute(Current, "REDRAW", "C" +
										  start_column.to_string + "-" +
										  end_column.to_string)
		end

	show_cell (line, column: INTEGER)
		-- If necessary scroll the visible area to make the given cell visible.
		require
			line > 0
			column > 0
		do
			iup_open.set_attribute(Current, "SHOW", line.to_string + ":" +
				column.to_string)
		end

	show_line (line: INTEGER)
		-- If necessary scroll the visible area to make the given line visible.
		require
			line > 0
		do
			iup_open.set_attribute(Current, "SHOW", line.to_string + ":*")
		end

	show_column (column: INTEGER)
		-- If necessary scroll the visible area to make the given column visible.
		require
			column > 0
		do
			iup_open.set_attribute(Current, "SHOW", "*:" + column.to_string)
		end

	-- Editing Attributes

	set_edit_mode (state: BOOLEAN)
		-- When set to True, programmatically puts the current cell in edition 
		-- mode, allowing the user to modify its value.
		do
			iup_open.set_attribute(Current, "EDITMODE", boolean_to_yesno(state))
		end

	is_visible_editing_control: BOOLEAN
		--	Informs if the editing control is visible (text or dropdown).
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "EDITMODE")

			Result := yesno_to_boolean(str)
		end

	set_edit_alignment (state: BOOLEAN)
		-- Sets the text box alignment to the column alignment when editing a 
		-- cell value. Default: False.
		do
			iup_open.set_attribute(Current, "EDITALIGN", boolean_to_yesno(state))
		end

	get_edited_cell: TUPLE[INTEGER, INTEGER]
		-- Returns the current cell being edited [line, column], or Void if 
		-- none. Can also be used during interaction while editing is being 
		-- performed and 'edit hide on focus' is False.
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "EDITCELL")

			if str /= Void then
				Result := components_of (str, ':')
			end
		end

	set_edit_fit_value (state: BOOLEAN)
		-- Enable a text box larger than the cell size of necessary, according to 
		-- the cell font and cell current value. While editing if more room is 
		-- necessary it will grow to the right. Default: False.
		do
			iup_open.set_attribute(Current, "EDITFITVALUE", boolean_to_yesno(state))
		end

	set_edit_hide_on_focus (state: BOOLEAN)
		-- When editing a cell if text box loses its focus, then editing ends. 
		-- Default: True. When set to False editing will continue and the matrix 
		-- can be scrolled, also when pressing Esc or Enter if the focus is at 
		-- the matrix it has the same effect as if pressed at the text box.
		do
			iup_open.set_attribute(Current, "EDITHIDEONFOCUS", boolean_to_yesno(state))
		end

	is_editing: BOOLEAN
		-- Returns True if the editing process is active for text or dropdown. It 
		-- is set to True after EDITION_CB, after MENUDROP_CB, before DROP_CB and 
		-- before the editing control is made visible. Set to False when editing 
		-- is about to end, after EDITION_CB and after the value has been 
		-- updated, but before the editing control is made invisible.
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "EDITING")

			Result := yesno_to_boolean(str)
		end

	set_edit_next (value: STRING)
		-- Controls how the next cell after editing is chosen. Can be LIN, COL, 
		-- LINCR, COLCR. Default: LIN.
		--
		-- LIN - go to the next line, if at last line then go to the next column 
		-- at the same line;
		-- LINCR - go to the next line, if at last line then go to the next 
		-- column at the first line;
		-- COL - go to the next column, if at last column then go to the next 
		-- line at the same column;
		-- COLCR - go to the next column, if at last column then go to the next 
		-- line at the first column;
		-- NONE - stay in the same cell.
		require
			is_valid_edit_next(value)
		do
			iup_open.set_attribute(Current, "EDITNEXT", value)
		end

	is_edit_text: BOOLEAN
		-- Returns True if the editing is being done by a text box.
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "EDITTEXT")

			Result := yesno_to_boolean(str)
		end

	is_edit_value: BOOLEAN
		-- Returns True if the display cell value being consulted will be used 
		-- for a text box initial value. Useful for being consulted inside the 
		-- translate and numeric callbacks.
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "EDITVALUE")

			Result := yesno_to_boolean(str)
		end

	is_cell_edited: BOOLEAN
		-- To be used inside the Value Changed and Value Edit callbacks.
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "CELL_EDITED")

			Result := yesno_to_boolean(str)
		end

	-- Text Editing Attributes

	set_caret (point: STRING)
		-- Allows specifying and verifying the caret position of the text box in 
		-- edition mode.
		--
		-- Character position of the insertion point. Its format depends in 
		-- MULTILINE=true. The first position, lin or col, is "1".
		--
		-- For multiple lines: a string with the "lin,col" format, where lin and 
		-- col are integer numbers corresponding to the caret's position.
		--
		-- For single line: a string in the "col" format, where col is an integer 
		-- number corresponding to the caret's position.
		--
		-- When lin is greater than the number of lines, the caret is placed at 
		-- the last line. When col is greater than the number of characters in 
		-- the given line, the caret is placed after the last character of the 
		-- line.
		--
		-- If the caret is not visible the text is scrolled to make it visible.
		--
		-- See the Notes below if using UTF-8 strings in GTK.
		do
			iup_open.set_attribute(Current, "CARET", point)
		end

	get_caret: STRING
		-- In Windows, if the element does not have the focus the returned value 
		-- is the position of the first character of the current selection. The 
		-- caret is only displayed if the element has the keyboard focus, but its 
		-- position can be changed even if not visible. When changed it will also 
		-- change the selection but the text will be scrolled only when it 
		-- receives the focus.
		do
			Result := iup_open.get_attribute(Current, "CARET")
		end

	insert_text (text: STRING)
		-- Inserts a text at the caret position of the text box in edition mode.
		do
			iup_open.set_attribute(Current, "INSERT", text)
		end

	set_mask_at (mask: STRING; line, column: INTEGER)
		-- Defines a mask that will filter interactive text 
		-- input. Use "REMOVE" to remove the mask.
		--
		-- Since the validation process is performed key by key when the user is 
		-- typing, an intermediate value cannot be typed if it does not follow 
		-- the mask rules.
		--
		-- If you set the VALUE attribute any text can be used. To set a value 
		-- that is validated by the current MASK use VALUEMASKED.
		--
		-- Pre-Defined Masks
		--
		-- Definition 	    Value         Description
		-- IUP_MASK_INT 	"[+/-]?/d+"    integer number
		-- IUP_MASK_UINT 	"/d+"          unsigned integer number
		-- IUP_MASK_FLOAT "[+/-]?(/d+/.?/d*|/./d+)" floating point number
		-- IUP_MASK_UFLOAT "(/d+/.?/d*|/./d+)" unsigned floating point number
		-- IUP_MASK_EFLOAT "[+/-]?(/d+/.?/d*|/./d+)([eE][+/-]?/d+)?" floating 
		--                               point number with exponential notation
		-- IUP_MASK_FLOATCOMMA 	"[+/-]?(/d+/,?/d*|/,/d+)" floating point number
		-- IUP_MASK_UFLOATCOMMA "(/d+/,?/d*|/,/d+)" unsigned floating point number
		--
		-- For more information see:
		-- http://webserver2.tecgraf.puc-rio.br/iup/en/attrib/iup_mask.html
		require
			line > 0
			column > 0
		do
			if mask.is_equal("REMOVE") then
				iup_open.set_attribute_id2_null(Current, "MASK", line, column)
			elseif mask_dictionary.has(mask) then
				iup_open.set_attribute_id2(Current, "MASK", line, column, mask_dictionary.at(mask))
			else
				iup_open.set_attribute_id2(Current, "MASK", line, column, mask)
			end
		end

	set_mask_case_insesitive_at (state: BOOLEAN; line, column: INTEGER)
		-- If True, will turn the filter case insensitive. Default: False.
		require
			line > 0
			column > 0
		do
			iup_open.set_attribute_id2(Current, "MASKCASEI", line, column, boolean_to_yesno(state))
		end

	set_mask_no_empty_at (state: BOOLEAN; line, column: INTEGER)
		-- If True, value can NOT be Void or empty. Default: False (can be 
		-- empty or Void).
		require
			line > 0
			column > 0
		do
			iup_open.set_attribute_id2(Current, "MASKNOEMPTY", line, column, boolean_to_yesno(state))
		end

	set_mask_decimal_symbol_at (value: STRING; line, column: INTEGER)
		-- The decimal symbol for string/float conversion. Can be "." or ",". 
		-- Must be set before MASKFLOAT.
		require
			line > 0
			column > 0
			is_valid_symbol (value)
		do
			iup_open.set_attribute_id2(Current, "MASKDECIMALSYMBOL", line, column, value)
		end

	set_mask_integer_at (min, max, line, column: INTEGER)
		-- Defines an integer mask with limits "min-max". It will replace MASK 
		-- using one of the pre-defined masks.
		require
			line > 0
			column > 0
		local
			str: STRING
		do
			str := min.to_string
			str.append_string(":")
			str.append_string(max.to_string)

			iup_open.set_attribute_id2(Current, "MASKINT", line, column, str)
		end

	set_mask_float_at (min, max: FLOAT; line, column: INTEGER)
		-- Defines a floating point mask with limits "min:max". It will replace 
		-- MASK using one of the pre-defined masks.
		require
			line > 0
			column > 0
		local
			str: STRING
		do
			str := min.to_string
			str.append_string(":")
			str.append_string(max.to_string)

			iup_open.set_attribute_id2(Current, "MASKFLOAT", line, column, str)
		end

	set_mask_at_line (mask: STRING; line: INTEGER)
		-- Defines a mask that will filter interactive text 
		-- input. Use "REMOVE" to remove the mask.
		--
		-- Since the validation process is performed key by key when the user is 
		-- typing, an intermediate value cannot be typed if it does not follow 
		-- the mask rules.
		--
		-- If you set the VALUE attribute any text can be used. To set a value 
		-- that is validated by the current MASK use VALUEMASKED.
		--
		-- Pre-Defined Masks
		--
		-- Definition 	    Value         Description
		-- IUP_MASK_INT 	"[+/-]?/d+"    integer number
		-- IUP_MASK_UINT 	"/d+"          unsigned integer number
		-- IUP_MASK_FLOAT "[+/-]?(/d+/.?/d*|/./d+)" floating point number
		-- IUP_MASK_UFLOAT "(/d+/.?/d*|/./d+)" unsigned floating point number
		-- IUP_MASK_EFLOAT "[+/-]?(/d+/.?/d*|/./d+)([eE][+/-]?/d+)?" floating 
		--                               point number with exponential notation
		-- IUP_MASK_FLOATCOMMA 	"[+/-]?(/d+/,?/d*|/,/d+)" floating point number
		-- IUP_MASK_UFLOATCOMMA "(/d+/,?/d*|/,/d+)" unsigned floating point number
		--
		-- For more information see:
		-- http://webserver2.tecgraf.puc-rio.br/iup/en/attrib/iup_mask.html
		require
			line > 0
		do
			if mask.is_equal("REMOVE") then
				iup_open.set_attribute_id2_null(Current, "MASK", line, -10)
			elseif mask_dictionary.has(mask) then
				iup_open.set_attribute_id2(Current, "MASK", line, -10, mask_dictionary.at(mask))
			else
				iup_open.set_attribute_id2(Current, "MASK", line, -10, mask)
			end
		end

	set_mask_case_insesitive_at_line (state: BOOLEAN; line: INTEGER)
		-- If True, will turn the filter case insensitive. Default: False.
		require
			line > 0
		do
			iup_open.set_attribute_id2(Current, "MASKCASEI", line, -10, boolean_to_yesno(state))
		end

	set_mask_no_empty_at_line (state: BOOLEAN; line: INTEGER)
		-- If True, value can NOT be Void or empty. Default: False (can be 
		-- empty or Void).
		require
			line > 0
		do
			iup_open.set_attribute_id2(Current, "MASKNOEMPTY", line, -10, boolean_to_yesno(state))
		end

	set_mask_decimal_symbol_at_line (value: STRING; line: INTEGER)
		-- The decimal symbol for string/float conversion. Can be "." or ",". 
		-- Must be set before MASKFLOAT.
		require
			line > 0
			is_valid_symbol (value)
		do
			iup_open.set_attribute_id2(Current, "MASKDECIMALSYMBOL", line, -10, value)
		end

	set_mask_integer_at_line (min, max, line: INTEGER)
		-- Defines an integer mask with limits "min-max". It will replace MASK 
		-- using one of the pre-defined masks.
		require
			line > 0
		local
			str: STRING
		do
			str := min.to_string
			str.append_string(":")
			str.append_string(max.to_string)

			iup_open.set_attribute_id2(Current, "MASKINT", line, -10, str)
		end

	set_mask_float_at_line (min, max: FLOAT; line: INTEGER)
		-- Defines a floating point mask with limits "min:max". It will replace 
		-- MASK using one of the pre-defined masks.
		require
			line > 0
		local
			str: STRING
		do
			str := min.to_string
			str.append_string(":")
			str.append_string(max.to_string)

			iup_open.set_attribute_id2(Current, "MASKFLOAT", line, -10, str)
		end

	set_mask_at_column (mask: STRING; column: INTEGER)
		-- Defines a mask that will filter interactive text 
		-- input. Use "REMOVE" to remove the mask.
		--
		-- Since the validation process is performed key by key when the user is 
		-- typing, an intermediate value cannot be typed if it does not follow 
		-- the mask rules.
		--
		-- If you set the VALUE attribute any text can be used. To set a value 
		-- that is validated by the current MASK use VALUEMASKED.
		--
		-- Pre-Defined Masks
		--
		-- Definition 	    Value         Description
		-- IUP_MASK_INT 	"[+/-]?/d+"    integer number
		-- IUP_MASK_UINT 	"/d+"          unsigned integer number
		-- IUP_MASK_FLOAT "[+/-]?(/d+/.?/d*|/./d+)" floating point number
		-- IUP_MASK_UFLOAT "(/d+/.?/d*|/./d+)" unsigned floating point number
		-- IUP_MASK_EFLOAT "[+/-]?(/d+/.?/d*|/./d+)([eE][+/-]?/d+)?" floating 
		--                               point number with exponential notation
		-- IUP_MASK_FLOATCOMMA 	"[+/-]?(/d+/,?/d*|/,/d+)" floating point number
		-- IUP_MASK_UFLOATCOMMA "(/d+/,?/d*|/,/d+)" unsigned floating point number
		--
		-- For more information see:
		-- http://webserver2.tecgraf.puc-rio.br/iup/en/attrib/iup_mask.html
		require
			column > 0
		do
			if mask.is_equal("REMOVE") then
				iup_open.set_attribute_id2_null(Current, "MASK", -10, column)
			elseif mask_dictionary.has(mask) then
				iup_open.set_attribute_id2(Current, "MASK", -10, column, mask_dictionary.at(mask))
			else
				iup_open.set_attribute_id2(Current, "MASK", -10, column, mask)
			end
		end

	set_mask_case_insesitive_at_column (state: BOOLEAN; column: INTEGER)
		-- If True, will turn the filter case insensitive. Default: False.
		require
			column > 0
		do
			iup_open.set_attribute_id2(Current, "MASKCASEI", -10, column, boolean_to_yesno(state))
		end

	set_mask_no_empty_at_column (state: BOOLEAN; column: INTEGER)
		-- If True, value can NOT be Void or empty. Default: False (can be 
		-- empty or Void).
		require
			column > 0
		do
			iup_open.set_attribute_id2(Current, "MASKNOEMPTY", -10, column, boolean_to_yesno(state))
		end

	set_mask_decimal_symbol_at_column (value: STRING; column: INTEGER)
		-- The decimal symbol for string/float conversion. Can be "." or ",". 
		-- Must be set before MASKFLOAT.
		require
			column > 0
			is_valid_symbol (value)
		do
			iup_open.set_attribute_id2(Current, "MASKDECIMALSYMBOL", -10, column, value)
		end

	set_mask_integer_at_column (min, max, column: INTEGER)
		-- Defines an integer mask with limits "min-max". It will replace MASK 
		-- using one of the pre-defined masks.
		require
			column > 0
		local
			str: STRING
		do
			str := min.to_string
			str.append_string(":")
			str.append_string(max.to_string)

			iup_open.set_attribute_id2(Current, "MASKINT", -10, column, str)
		end

	set_mask_float_at_column (min, max: FLOAT; column: INTEGER)
		-- Defines a floating point mask with limits "min:max". It will replace 
		-- MASK using one of the pre-defined masks.
		require
			column > 0
		local
			str: STRING
		do
			str := min.to_string
			str.append_string(":")
			str.append_string(max.to_string)

			iup_open.set_attribute_id2(Current, "MASKFLOAT", -10, column, str)
		end

	set_multi_line (state: BOOLEAN)
		-- Allows the edition of multiple lines. Use Shift+Enter to add lines. 
		-- Enter will end the editing.
		do
			iup_open.set_attribute(Current, "MULTILINE", boolean_to_yesno(state))
		end

	set_selection (value: STRING)
		-- Allows specifying and verifying selection interval of the text box in 
		-- edition mode. The first position, lin or col, is "1".
		--
		-- For multiple lines: a string in the "lin1,col1:lin2,col2" format, 
		-- where lin1, col1, lin2 and col2 are integer numbers corresponding to 
		-- the selection's interval. col2 correspond to the character after the 
		-- last selected character.
		--
		-- For single line: a string in the "col1:col2" format, where col1 and 
		-- col2 are integer numbers corresponding to the selection's interval. 
		-- col2 correspond to the character after the last selected character.
		--
		-- In Windows, when changing the selection the caret position is also 
		-- changed.
		--
		-- See the Notes below if using UTF-8 strings in GTK.
		do
			iup_open.set_attribute(Current, "SELECTION", value)
		end

	select_all
		-- Select all the text.
		do
			iup_open.set_attribute(Current, "SELECTION", "ALL")
		end
	
	deselect_all
		-- Deselect.
		do
			iup_open.set_attribute(Current, "SELECTION", "NONE")
		end

	-- Canvas Attributes (inheritable)

	set_border (state: BOOLEAN)
		-- (creation only): Shows a border around the canvas. Default: "False".
		do
			Precursor (state)
		end

	set_scroll_bar (state: BOOLEAN)
		-- (creation only): Associates a horizontal and/or vertical scrollbar to 
		-- the canvas. Default: "True". The secondary attributes are all non 
		-- inheritable.	
		do
			Precursor (state)
		end

	-- Coordination to pos
	convert_xy_to_pos (x, y: INTEGER): INTEGER
		-- To convert (x,y) coordinates in the cell position, then use 
		-- "text_convert_pos_to_lin_col" to convert pos into (lin,col).
		do
			Result := iup_open.iup_convert_xy_to_pos (Current, x, y)	
		end

	-- Callbacks

	set_cb_action (act: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER, INTEGER, INTEGER, STRING], STRING])
		-- Action generated when a keyboard event occurs.
		--
		-- ih: identifier of the element that activated the event.
		--
		-- key: Identifier of the typed key. Please refer to the Keyboard Codes 
		-- table for a list of possible values.
		--
		-- lin, col: Coordinates of the selected cell.
		--
		-- edition: 1 if the cell is in edition mode, and 0 if it is not.
		--
		-- value: When EDITMODE=False is the cell current value, but if the type 
		-- key is a valid character then contains a string with that character. 
		-- When EDITMODE=True depends on the editing field type. If a dropdown, 
		-- then it is an empty string (""). If a text, and the type key is a 
		-- valid character then it is the future value of the text field, if not 
		-- a valid character then it is the cell current value. Notice that this 
		-- value can be Void if the cell does not have a value and the key 
		-- pressed is not a character.
		--
		-- Returns: IUP_DEFAULT validates the key, IUP_IGNORE ignores the key, 
		-- IUP_CONTINUE forwards the key to IUPs conventional processing, or the 
		-- identifier of the key to be treated by the matrix.
		local
			operation: INTEGER
		do
			cb_action := act

			if cb_action /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "ACTION_CB", "NONEEDED", operation)
		end

	set_cb_click (act: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER, STRING], STRING])
		-- Action generated when any mouse button is pressed over a cell. This 
		-- callback is always called after other callbacks. When 
		-- EDITHIDEONFOCUS=False and editing is on going the callback 
		-- EDITCLICK_CB with the same parameters will also be called right before 
		-- this one.
		--
		-- ih: identifier of the element that activated the event.
		--
		-- lin, col: Coordinates of the cell where the mouse button was pressed.
		--
		-- status: Status of the mouse buttons and some keyboard keys at the 
		-- moment the event is generated. The same macros used for BUTTON_CB can 
		-- be used for this status.
		--
		-- Returns: To avoid the display update return IUP_IGNORE.
		local
			operation: INTEGER
		do
			cb_click := act

			if cb_click /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "CLICK_CB", "NONEEDED", operation)
		end

	set_cb_column_resise (act: FUNCTION[TUPLE[IUP_MATRIX, INTEGER], STRING])
		-- Action generated when a column is interactively resized:
		--
		-- ih: identifier of the element that activated the event.
		-- col: Column that had its size changed.
		local
			operation: INTEGER
		do
			cb_colresize := act

			if cb_colresize /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "COLRESIZE_CB", "NONEEDED", operation)
		end

	set_cb_release (act: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER, STRING], STRING])
		-- Action generated when any mouse button is released over a cell. This 
		-- callback is always called after other callbacks. When 
		-- EDITHIDEONFOCUS=False and editing is on going the callback 
		-- EDITRELEASE_CB with the same parameters will also be called right 
		-- before this one.
		--
		-- ih:       identifier of the element that activated the event.
		-- lin, col: Coordinates of the cell where the mouse button was pressed.
		-- status:   Status of the mouse buttons and some keyboard keys at the 
		--           moment the event is generated. The same macros used for 
		--           BUTTON_CB can be used for this status.
		--
		-- Returns: To avoid the display update return IUP_IGNORE.
		local
			operation: INTEGER
		do
			cb_release := act

			if cb_release /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "RELEASE_CB", "NONEEDED", operation)
		end

	set_cb_resize_matrix (act: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER], STRING])
		-- Action generated after the element size has been updated but before 
		-- the cells have been actually refreshed.
		--
		-- ih:    identifier of the element that activated the event.
		-- width: the width of the internal element size in pixels not 
		--        considering the BORDER size (client size).
		-- height: the height of the internal element size in pixels not 
		-- considering the BORDER size (client size).
		local
			operation: INTEGER
		do
			cb_resizematrix := act

			if cb_resizematrix /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "RESIZEMATRIX_CB", "NONEEDED", operation)
		end

	set_cb_toggle_value (act: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER, INTEGER], STRING])
		-- Action generated when a toggle button is pressed.
		--
		-- ih: identifier of the element that activated the event.
		-- lin, col: Coordinates of the cell where the mouse button was pressed.
		-- status: Value of the toggle. Can be 1 or 0.
		local
			operation: INTEGER
		do
			cb_togglevalue := act

			if cb_togglevalue /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "TOGGLEVALUE_CB", "NONEEDED", operation)
		end

	set_cb_value_changed (act: FUNCTION[TUPLE[IUP_MATRIX], STRING])
		-- Called after the value was interactively changed by the user or after 
		-- a group of values where programmatically changed in a single 
		-- operation. When it was interactively changed the temporary attribute 
		-- CELL_EDITED will be set to "True" during the callback
		local
			operation: INTEGER
		do
			cb_valuechanged := act

			if cb_valuechanged /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "VALUECHANGED_CB", "NONEEDED", operation)
		end

	set_cb_mouse_move (act: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER], STRING])
		-- Action generated to notify the application that the mouse has moved 
		-- over the matrix. When EDITHIDEONFOCUS=False and editing is on going 
		-- the callback EDITMOUSEMOVE_CB with the same parameters will also be 
		-- called right before this one.
		--
		-- ih:       identifier of the element that activated the event.
		--	lin, col: Coordinates of the cell that the mouse cursor is 
		--	          currently on.
		local
			operation: INTEGER
		do
			cb_mousemove := act

			if cb_mousemove /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "MOUSEMOVE_CB", "NONEEDED", operation)
		end

	set_cb_enter_item (act: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER], STRING])
		-- Action generated when a matrix cell is selected, becoming the current 
		-- cell. Also called when matrix is getting focus. Also called when focus 
		-- is changed because lines or columns were added or removed.
		--
		-- ih: identifier of the element that activated the event.
		--	lin, col: Coordinates of the selected cell.
		local
			operation: INTEGER
		do
			cb_enteritem := act

			if cb_enteritem /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "ENTERITEM_CB", "NONEEDED", operation)
		end

	set_cb_leave_item (act: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER], STRING])
		-- Action generated when a cell is no longer the current cell. Also 
		-- called when the matrix is losing focus.
		--
		-- ih: identifier of the element that activated the event.
		-- lin, col: Coordinates of the cell which is no longer the current cell.
		--
		-- Returns: IUP_IGNORE prevents the current cell from changing, but this 
		-- will not work when the matrix is losing focus.  If you try to move to 
		-- beyond matrix borders the cell will lose focus and then get it again, 
		-- so leaveitem_cb and enteritem_cb will be called.
		local
			operation: INTEGER
		do
			cb_leaveitem := act

			if cb_leaveitem /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "LEAVEITEM_CB", "NONEEDED", operation)
		end

	set_cb_scroll_top (act: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER], STRING])
		-- Action generated when the matrix is scrolled with the scrollbars or 
		-- with the keyboard. Can be used together with the ORIGIN and 
		-- ORIGINOFFSET attributes to synchronize the movement of two or more 
		-- matrices.
		--
		-- ih: identifier of the element that activated the event.
		-- lin, col: Coordinates of the cell currently in the upper left corner 
		-- of the matrix.
		local
			operation: INTEGER
		do
			cb_scrolltop := act

			if cb_scrolltop /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "SCROLLTOP_CB", "NONEEDED", operation)
		end

	set_cb_background_color (act: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER, POINTER, POINTER, POINTER], STRING])
		-- Action generated to retrieve the background color of a cell when it 
		-- needs to be redrawn.
		--
		-- ih: identifier of the element that activated the event.
		-- lin, col: Coordinates of the cell.
		-- red, green, blue: the cell background color.
		--
		-- Returns: If IUP_IGNORE, the values are ignored and the attribute 
		-- defined background color will be used. If returns IUP_DEFAULT the 
		-- returned values will be used as the background color.
		local
			operation: INTEGER
		do
			cb_bgcolor := act

			if cb_bgcolor /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "BGCOLOR_CB", "NONEEDED", operation)
		end

	set_cb_foreground_color (act: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER, POINTER, POINTER, POINTER], STRING])
		-- Action generated to retrieve the foreground color of a cell when it 
		-- needs to be redrawn.
		--
		-- ih: identifier of the element that activated the event.
		-- lin, col: Coordinates of the cell.
		-- red, green, blue: the cell foreground color.
		--
		-- Returns: If IUP_IGNORE, the values are ignored and the attribute 
		-- defined foreground color will be used. If returns IUP_DEFAULT the 
		-- returned values will be used as the foreground color.
		local
			operation: INTEGER
		do
			cb_fgcolor := act

			if cb_fgcolor /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "FGCOLOR_CB", "NONEEDED", operation)
		end

	set_cb_font (act: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER], STRING])
		-- Action generated to retrieve the font of a cell. Called both for 
		-- common cells and for line and column titles.
		--
		-- ih: identifier of the element that activated the event.
		-- lin, col: Coordinates of the cell.
		--
		-- Returns: Must return a font or NULL to use the the attribute defined 
		-- font.
		local
			operation: INTEGER
		do
			cb_font := act

			if cb_font /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "FONT_CB", "NONEEDED", operation)
		end

	set_cb_type (act: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER], STRING])
		-- Action generated to retrieve the type of a cell value. Called both for 
		-- common cells and for line and column titles.
		--
		-- ih: identifier of the element that activated the event.
		-- lin, col: Coordinates of the cell.
		--
		-- Returns: Must return "TEXT", "COLOR", "FILL" or "IMAGE".
		local
			operation: INTEGER
		do
			cb_type := act

			if cb_type /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "TYPE_CB", "NONEEDED", operation)
		end

	set_cb_draw (act: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER, INTEGER, INTEGER, INTEGER, INTEGER, CD_IUP], STRING])
		--  Called when a specific cell needs to be redrawn.
		--
		-- ih: identifier of the element that activated the event.
		-- line, column: the grid position inside the control that is being 
		--     redrawn, in grid coordinates.
		-- xmin, xmax, ymin, ymax: the raster bounding box of the redrawn cells, 
		--     where the application can use CD functions to draw anything. If 
		--     the attribute IUP_CLIPPED is set (the default), all CD graphical 
		--     primitives is clipped to the bounding region.
		-- canvas: internal canvas CD used to draw the cells.
		--
		-- Returns: "IUP_DEFAULT", "IUP_CONTINUE" or "IUP_IGNORE"
		local
			operation: INTEGER
		do
			cb_draw := act

			if cb_draw /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "DRAW_CB", "NONEEDED", operation)
		end

	set_cb_drop_check (act: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER], STRING])
		-- Action generated before the current cell is redrawn to determine if a 
		-- dropdown/popup menu feedback or a toggle should be shown. If this 
		-- action is not registered, no feedback will be shown. If the callback 
		-- is defined and return IUP_DEFAULT for a cell, to show the 
		-- dropdown/popup menu the user can simply do a single click in the drop 
		-- feedback area of that cell.
		--
		-- ih: identifier of the element that activated the event.
		-- lin, col: Coordinates of the cell.
		--
		-- Returns: IUP_DEFAULT will show a drop feedback, IUP_CONTINUE will show 
		-- and enable the toggle button, or IUP_IGNORE to draw nothing.
		local
			operation: INTEGER
		do
			cb_dropcheck := act

			if cb_dropcheck /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "DROPCHECK_CB", "NONEEDED", operation)
		end

	set_cb_translate_value (act: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER, STRING], STRING])
		-- Action generated to translate the value of a cell during display and 
		-- size computation. Called both for common cells and for line and column 
		-- titles.
		--
		-- ih: identifier of the element that activated the event.
		-- lin, col: Coordinates of the cell.
		-- value: original cell value
		--
		-- Returns: the string to be drawn. 
		local
			operation: INTEGER
		do
			cb_translatevalue := act

			if cb_translatevalue /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "TRANSLATEVALUE_CB", "NONEEDED", operation)
		end

	set_cb_drop (act: FUNCTION[TUPLE[IUP_MATRIX, IUP_DROP, INTEGER, INTEGER], STRING])
		-- Action generated before the current cell enters edition mode to 
		-- determine if a text field or a dropdown list will be shown. It is 
		-- called after EDITION_CB. If this action is not registered, a text field
		-- will be shown. Its return determines what type of element will be used 
		-- in the edition mode. If the selected type is a dropdown, the values 
		-- appearing in the dropdown must be fulfilled in this callback, just like
		-- elements are added to any list (the drop parameter is the handle of the
		-- dropdown list to be shown). You should also set the lists current value
		-- ("VALUE"), the default is always "1". The previously cell value can be 
		-- verified from the given drop Ihandle via the "PREVIOUSVALUE" 
		-- attribute.
		--
		-- ih: identifier of the element that activated the event.
		-- drop: Identifier of the dropdown list which will be shown to the user.
		-- lin, col: Coordinates of the current cell.
		--
		-- Returns: IUP_IGNORE to show a text-edition field, or IUP_DEFAULT to 
		-- show a dropdown field.
		local
			operation: INTEGER
		do
			cb_drop := act

			if cb_drop /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "DROP_CB", "NONEEDED", operation)
		end

	set_cb_menu_drop (act: FUNCTION[TUPLE[IUP_MATRIX, IUP_DROP, INTEGER, INTEGER], STRING])
		-- Action generated before the current cell enters edition mode to 
		-- determine if a popup menu will be shown instead of a text field or a 
		-- dropdown. If this action is registered and retunr IUP_DEFAULT the 
		-- DROP_CB callback is not called, and the popup menu is shown. Like 
		-- DROP_CB, it is called after EDITION_CB. The values appearing as menu 
		-- items in the popup menu must be fulfilled in this callback, like 
		-- elements are added to a list (the drop parameter is the handle of the 
		-- popup menu to be shown, but the actual items will be added later by 
		-- the internal processing). You could also set the "VALUE" attribute 
		-- that will add a mark to the menu item with the same number. If IMAGEid 
		-- is set then an IMAGE attribute will be set at the correspondent menu 
		-- item. The previously cell value can be verified from the given drop 
		-- Ihandle via the "PREVIOUSVALUE" attribute.
		--
		-- ih: identifier of the element that activated the event.
		-- drop: Identifier of the popup menu which will be shown to the user.
		-- lin, col: Coordinates of the current cell.
		--
		-- Returns: IUP_IGNORE to not show the menu for the given cell, DROP_CB 
		-- will then be called.
		local
			operation: INTEGER
		do
			cb_menudrop := act

			if cb_menudrop /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "MENUDROP_CB", "NONEEDED", operation)
		end

	set_cb_drop_select (act: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER, IUP_DROP, STRING, INTEGER, INTEGER], STRING])
		-- Action generated when an element in the dropdown list or the popup 
		-- menu is selected. For the dropdown, if returns IUP_CONTINUE the value 
		-- is accepted as a new value and the matrix leaves edition mode, else 
		-- the item is selected and editing remains. For the popup menu the 
		-- returned value is ignored.
		--
		-- ih:       identifier of the element that activated the event.
		-- lin, col: Coordinates of the current cell.
		-- drop:     Identifier of the dropdown list or the popup menu shown to 
		--           the user.
		-- t:        Text of the item whose state was changed.
		-- i:        Number of the item whose state was changed.
		-- v:        Indicates if item was selected or unselected (1 or 0). 
		--           Always 1 for the popup menu.
		local
			operation: INTEGER
		do
			cb_dropselect := act

			if cb_dropselect /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "DROPSELECT_CB", "NONEEDED", operation)
		end

	set_cb_edition (act: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER, INTEGER, INTEGER], STRING])
		-- Action generated when the current cell enters or leaves the edition 
		-- mode. Not called if READONLY=True.
		--
		-- ih:       identifier of the element that activated the event.
		-- lin, col: Coordinates of the current cell.
		-- mode:     1 if the cell has entered the edition mode, or 0 if the cell 
		--           has left the edition mode.
		-- update:   used when mode=0 to identify if the value will be updated 
		--           when the callback returns with IUP_DEFAULT. (since 3.0)
		--
		-- Returns: can be IUP_DEFAULT, IUP_IGNORE or IUP_CONTINUE.
		--
		-- If the callback does not exists the cell can always be edited and the 
		-- new value is always accepted.
		--
		-- When editing is started, mode=1 and update=0. Editing is allowed if 
		-- the callback returns IUP_DEFAULT, so to make the cell read-only return 
		-- IUP_IGNORE.
		--
		-- When editing ends, mode=0 and update can be 0 or 1. The new value is 
		-- accepted only if the callback returns IUP_DEFAULT. The VALUE attribute 
		-- when consulted inside the callback returns the new value that will be 
		-- updated to the cell. update=0 only when the user cancel the editing by 
		-- pressing the Esc key. If the callback returns IUP_CONTINUE the edit 
		-- mode is ended and the new value will not be updated, so the 
		-- application can set a different value during the callback (useful to 
		-- format the new value). If the callback returns IUP_IGNORE the editing 
		-- is not ended, with several exceptions: the Esc key was used; the 
		-- matrix size, scroll or visibility was changed during edition mode; a 
		-- click in another cell; or the edit control loses its focus.
		--
		-- This callback is also called when the user press Del to clear the cell 
		-- contents or other multiple cell editing. The callback will simply 
		-- validate the operation for each cell been cleared by checking if the 
		-- matrix is read-only or if the cell is read-only. In this situation it 
		-- is called with mode=1 and update=1. When in normal mode (not callback 
		-- mode) the new value can not be refused, but you can use the 
		-- VALUE_EDIT_CB to reset a new value or use the VALUECHANGED_CB to check 
		-- all the new values after they where changed.
		local
			operation: INTEGER
		do
			cb_edition := act

			if cb_edition /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "EDITION_CB", "NONEEDED", operation)
		end

	set_cb_value (act: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER], STRING])
		-- Action generated to retrieve the value of a cell. Called both for 
		-- common cells and for line and column titles.
		--
		-- ih: identifier of the element that activated the event.
		-- lin, col: Coordinates of the cell.
		--
		-- Returns: the string to be drawn.
		--
		-- IMPORTANT: The existence of this callback defines the callback 
		-- operation mode of the matrix when it is mapped.
		local
			operation: INTEGER
		do
			cb_value := act

			if cb_value /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "VALUE_CB", "NONEEDED", operation)
		end

	set_cb_value_edit (act: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER, STRING], STRING])
		-- Action generated to notify the application that the value of a cell 
		-- was changed. Never called when READONLY=YES. This callback is usually 
		-- set in callback mode, but also works in normal mode. When in normal 
		-- mode, it is called after the new value has been internally stored, so 
		-- to refuse the new value simply reset the cell to the desired value. 
		-- When it was interactively changed the temporary attribute CELL_EDITED 
		-- will be set to Yes during the callback.
		--
		-- ih: identifier of the element that activated the event.
		-- lin, col: Coordinates of the cell.
		-- newval: String containing the new cell value
		--
		-- IMPORTANT: if VALUE_CB is defined and VALUE_EDIT_CB is not defined 
		-- when the matrix is mapped it will be read-only.	
		local
			operation: INTEGER
		do
			cb_value_edit := act

			if cb_value_edit /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "VALUE_EDIT_CB", "NONEEDED", operation)
		end

	set_cb_mark (act: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER], INTEGER])
		-- Action generated to retrieve the selection state of a cell. Called 
		-- only for common cells, only when MARKMODE=CELL and only in callback 
		-- mode.
		--
		-- ih: identifier of the element that activated the event.
		-- lin, col: Coordinates of the cell.
		--
		-- Returns: the selection state (marked=1, not marked 0). If not defined 
		-- the attribute "MARKL:C" will be returned.
		local
			operation: INTEGER
		do
			cb_mark := act

			if cb_mark /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "MARK_CB", "NONEEDED", operation)
		end

	set_cb_mark_edit (act: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER, INTEGER], STRING])
		-- Action generated to notify the application that the selection state of 
		-- a cell was changed. Since it is a notification, it cannot refuse the 
		-- mark modification. Called only for common cells, only when 
		-- MARKMODE=CELL and only in callback mode.
		--
		-- ih: identifier of the element that activated the event.
		-- lin, col: Coordinates of the cell.
		-- marked: selection state (marked=1, not marked 0).
		--
		-- If not defined the attribute "MARKL:C" will be updated. So if you 
		-- define the MARKEDIT_CB the "MARKL:C" will NOT be updated and the 
		-- callback MARK_CB must return the selection state of the cell. If you 
		-- do not want to implement the MARK_CB callback then set the "MARKL:C" 
		-- attribute inside the MARKEDIT_CB callback.
		local
			operation: INTEGER
		do
			cb_markedit := act

			if cb_markedit /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "MARKEDIT_CB", "NONEEDED", operation)
		end

feature {IUP}

	-- Matrix

	execute_action_fniiiis (key, lin, col, edition: INTEGER; value: STRING): STRING
		do
			Result := cb_action.item([Current, key, lin, col, edition, value])
		end

	execute_click_fniis (lin, col: INTEGER; status: STRING): STRING
		do
			Result := cb_click.item([Current, lin, col, status])
		end

	execute_colresize (col: INTEGER): STRING
		do
			Result := cb_colresize.item([Current, col])
		end

	execute_release (lin, col: INTEGER; status: STRING): STRING
		do
			Result := cb_release.item([Current, lin, col, status])
		end

	execute_resizematrix (width, height: INTEGER): STRING
		do
			Result := cb_resizematrix.item([Current, width, height])
		end

	execute_togglevalue_fniii (lin, col, status: INTEGER): STRING
		do
			Result := cb_togglevalue.item([Current, lin, col, status])
		end

	execute_valuechanged: STRING
		do
			Result := cb_valuechanged.item([Current])
		end	

	execute_mousemove (lin, col: INTEGER): STRING
		do
			Result := cb_mousemove.item([Current, lin, col])
		end

	execute_enteritem (lin, col: INTEGER): STRING
		do
			Result := cb_enteritem.item([Current, lin, col])
		end

	execute_leaveitem (lin, col: INTEGER): STRING
		do
			Result := cb_leaveitem.item([Current, lin, col])
		end

	execute_scrolltop (lin, col: INTEGER): STRING
		do
			Result := cb_scrolltop.item([Current, lin, col])
		end

	execute_bgcolor (lin, col: INTEGER; red, green, blue: POINTER): STRING
		do
			Result := cb_bgcolor.item([Current, lin, col, red, green, blue])
		end

	execute_fgcolor (lin, col: INTEGER; red, green, blue: POINTER): STRING
		do
			Result := cb_fgcolor.item([Current, lin, col, red, green, blue])
		end

	execute_font (lin, col: INTEGER): STRING
		do
			Result := cb_font.item([Current, lin, col])
		end

	execute_type (lin, col: INTEGER): STRING
		do
			Result := cb_type.item([Current, lin, col])
		end

	execute_draw (line, column, xmin, xmax, ymin, ymax: INTEGER; canvas: POINTER): STRING
		do
			Result := cb_draw.item([Current, line, column, xmin, xmax, ymin, ymax, internal_cd(canvas)])
		end

	execute_dropcheck (lin, col: INTEGER): STRING
		do
			Result := cb_dropcheck.item([Current, lin, col])
		end

	execute_translatevalue (lin, col: INTEGER; value: STRING): STRING
		do
			Result := cb_translatevalue.item([Current, lin, col, value])
		end

	execute_drop (drop: IUP_DROP; lin, col: INTEGER): STRING
		do
			Result := cb_drop.item([Current, drop, lin, col])
		end

	execute_menudrop (drop: IUP_DROP; lin, col: INTEGER): STRING
		do
			Result := cb_menudrop.item([Current, drop, lin, col])
		end

	execute_dropselect (lin, col: INTEGER; drop: IUP_DROP; t: STRING; i, v: INTEGER): STRING
		do
			Result := cb_dropselect.item([Current, lin, col, drop, t, i, v])
		end

	execute_edition (lin, col, mode, update: INTEGER): STRING
		do
			Result := cb_edition.item([Current, lin, col, mode, update])
		end

	execute_value (lin, col: INTEGER): STRING
		do
			Result := cb_value.item([Current, lin, col])
		end

	execute_value_edit (lin, col: INTEGER; newval: STRING): STRING
		do
			Result := cb_value_edit.item([Current, lin, col, newval])
		end

	execute_mark (lin, col: INTEGER): INTEGER
		do
			Result := cb_mark.item([Current, lin, col])
		end

	execute_markedit (lin, col, marked: INTEGER): STRING
		do
			Result := cb_markedit.item([Current, lin, col, marked])
		end


feature {}

	-- For callbacks
	
	cb_action: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER, INTEGER, INTEGER, STRING], STRING]
	cb_click: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER, STRING], STRING]
	cb_colresize: FUNCTION[TUPLE[IUP_MATRIX, INTEGER], STRING]
	cb_release: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER, STRING], STRING]
	cb_resizematrix: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER], STRING]
	cb_togglevalue: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER, INTEGER], STRING]
	cb_valuechanged: FUNCTION[TUPLE[IUP_MATRIX], STRING]
	cb_mousemove: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER], STRING]
	cb_enteritem: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER], STRING]
	cb_leaveitem: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER], STRING]
	cb_scrolltop: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER], STRING]
	cb_bgcolor: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER, POINTER, POINTER, POINTER], STRING]
	cb_fgcolor: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER, POINTER, POINTER, POINTER], STRING]
	cb_font: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER], STRING]
	cb_type: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER], STRING]
	cb_draw: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER, INTEGER, INTEGER, INTEGER, INTEGER, CD_IUP], STRING]
	cb_dropcheck: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER], STRING]
	cb_translatevalue: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER, STRING], STRING]
	cb_drop: FUNCTION[TUPLE[IUP_MATRIX, IUP_DROP, INTEGER, INTEGER], STRING]
	cb_menudrop: FUNCTION[TUPLE[IUP_MATRIX, IUP_DROP, INTEGER, INTEGER], STRING]
	cb_dropselect: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER, IUP_DROP, STRING, INTEGER, INTEGER], STRING]
	cb_edition: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER, INTEGER, INTEGER], STRING]
	cb_value: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER], STRING]
	cb_value_edit: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER, STRING], STRING]
	cb_mark: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER], INTEGER]
	cb_markedit: FUNCTION[TUPLE[IUP_MATRIX, INTEGER, INTEGER, INTEGER], STRING]

	-- Mask dictionary
	
	mask_dictionary: DICTIONARY[STRING, STRING]

	-- Validations

	is_valid_lin_align (value: STRING): BOOLEAN
		do
			if value.is_equal("ATOP") or
				value.is_equal("ACENTER") or
				value.is_equal("ABOTTOM") then
				Result := True
			else
				Result := False
			end
		end

	is_valid_col_align (value: STRING): BOOLEAN
		do
			if value.is_equal("ALEFT") or
				value.is_equal("ACENTER") or
				value.is_equal("ARIGHT") then
				Result := True
			else
				Result := False
			end
		end

	is_valid_type_cell (value: STRING): BOOLEAN
		do
			if value.is_equal("TEXT") or
				value.is_equal("COLOR") or
				value.is_equal("FILL") or
				value.is_equal("IMAGE") then
				Result := True
			else
				Result := False
			end
		end

	is_valid_sort_sign (value: STRING): BOOLEAN
		do
			if value.is_equal("UP") or
				value.is_equal("DOWN") or
				value.is_equal("NO") then
				Result := True
			else
				Result := False
			end
		end

	is_valid_symbol (value: STRING): BOOLEAN
		do
			if value.is_equal(".") or
				value.is_equal(",") then
				Result := True
			else
				Result := False
			end
		end

	is_valid_edit_next (value: STRING): BOOLEAN
		do
			if value.is_equal("LIN") or
				value.is_equal("LINCR") or
				value.is_equal("COL") or
				value.is_equal("COLCR") or
				value.is_equal("NONE") then
				Result := True
			else
				Result := False
			end
		end

	-- Converts

	string_to_boolean(value: STRING): BOOLEAN
		do
			if value.is_equal("0") then
				Result := False
			else
				Result := True
			end
		end

	array_to_marks (array: FAST_ARRAY[BOOLEAN]): STRING
		local
			x: INTEGER
			s: STRING
		do
         create s.with_capacity(array.count)
			
			from
				x := 0
         until
				x = array.count
         loop
				s.append_character(array.item(x).to_character)
				
				x := x + 1
         end

			Result := s
		end

	array2_to_marks (array: FAST_ARRAY2[BOOLEAN]): STRING
		local
			x, y: INTEGER
			s: STRING
		do
         create s.with_capacity(array.count1*array.count2)
			
			from
				x := 0
         until
				x = array.count2
         loop
				from
					y := 0
				until
					y = array.count1
				loop
					s.append_character(array.item(x, y).to_character)
					
					y := y + 1
				end
				
				x := x + 1
         end

			Result := s
		end

	marks_to_array(values: STRING; size: INTEGER): FAST_ARRAY[BOOLEAN]
		local
			i: INTEGER
			element: BOOLEAN
			iterator: ITERATOR[CHARACTER]
			mtx: FAST_ARRAY[BOOLEAN]
		do
			iterator := values.new_iterator
			create mtx.make(size)

			from
				i := 0
            iterator.start
         until
            iterator.is_off
         loop
				if iterator.item.is_equal('1') then
					element := True
				else
					element := False
				end
				mtx.put(element, i)
				
            i := i + 1
            iterator.next
         end

			Result := mtx
		end

	marks_to_array2(values: STRING): FAST_ARRAY2[BOOLEAN]
		local
			i: INTEGER
			element: BOOLEAN
			iterator: ITERATOR[CHARACTER]
			mtx: FAST_ARRAY2[BOOLEAN]
		do
			iterator := values.new_iterator
			create mtx.make(get_number_of_lines, get_number_of_columns)

			from
				i := 0
            iterator.start
         until
            iterator.is_off
         loop
				if iterator.item.is_equal('1') then
					element := True
				else
					element := False
				end
				mtx.put(element, i//mtx.count2, i\\mtx.count1)
				
            i := i + 1
            iterator.next
         end

			Result := mtx
		end

	components_of_alignment (value: STRING): TUPLE[STRING, STRING]
		local
			i, c: INTEGER
			line, col: STRING
			tup: TUPLE[STRING, STRING]
		do			
			if value.has(':') then
				i := value.index_of(':', 1)
				c := value.count
				
				if not i.is_equal(1) then
					line := value.substring(1, i - 1)
				else
					line := "0"
				end
				
				if not i.is_equal(c) then
					col := value.substring(i + 1, c)
				else
					col := "0"
				end

				tup := [line, col]
				Result := tup
			else
				io.put_string("Unable to get the components %N")
			end
		end
	
	-- Internals

	int_matrix(action: POINTER): POINTER
		external "plug_in"
      alias "{
         location: "${sys}/plugins"
         module_name: "iup"
         feature_name: "IupMatrix"
         }"
      end

	create_mask_dictionary
		do
			mask_dictionary := {HASHED_DICTIONARY[STRING, STRING] <<
					   "[+/-]?(/d+/.?/d*|/./d+)", "IUP_MASK_FLOAT";
						"(/d+/.?/d*|/./d+)", "IUP_MASK_UFLOAT";
						"[+/-]?(/d+/.?/d*|/./d+)([eE][+/-]?/d+)?", "IUP_MASK_EFLOAT";
					   "[+/-]?(/d+/,?/d*|/,/d+)", "IUP_MASK_FLOATCOMMA";
						"(/d+/,?/d*|/,/d+)", "IUP_MASK_UFLOATCOMMA";
						"[+/-]?/d+", "IUP_MASK_INT";
						"/d+", "IUP_MASK_UINT" >> }
		end

end

-- The MIT License (MIT)

-- Copyright (c) 2016, 2017, 2018, 2019, 2022 by German A. Arias

-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this software and associated documentation files (the "Software"), to deal
-- in the Software without restriction, including without limitation the rights
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-- copies of the Software, and to permit persons to whom the Software is
-- furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in 
-- all copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-- SOFTWARE.
